feat(ci): 接入论坛发帖步骤(默认关闭)

工作流新增 "Post to forum" 步骤,位于建站之后、提交之前:
读同一次运行生成的 data/deals.json 发帖,不重复抓取。

默认关闭
- LDR_FORUM_ENABLED 默认 false,该步骤只打印「已关闭」并退出
- LDR_FORUM_DRY_RUN 默认 true,即使开启也只演练
- 想真正发帖:仓库 Variables 设 LDR_FORUM_ENABLED=true
  且 LDR_FORUM_DRY_RUN=false

关键修正:把 data/forum_posted.json 纳入提交
这是幂等依据 —— 不提交的话每次运行都读不到记录,
同一活动会被反复搬运到论坛。

CLI 新增 --forum-only:只读现有 deals.json 发帖,
不抓取也不建站,便于与抓取步骤解耦。

验证:178 测试通过;YAML 解析正常(10 个步骤)。
This commit is contained in:
gungun88 committed 2026-10-16 20:08:06 +08:00
1 parent 0ed581e551
commit 7db5d526e7
2 files changed
+69 -2

No files matched your search

+24 -2
View File
@@ -80,11 +80,33 @@ jobs:
retention-days: 7
if-no-files-found: error
- name: Post to forum
# 把优惠帖搬运到 LowSeek 论坛。
#
# 默认关闭:LDR_FORUM_ENABLED 未设置时该步骤只打印「已关闭」并退出,
# 不会发布任何内容。想开启时在仓库 Variables 里设:
# LDR_FORUM_ENABLED = true
# LDR_FORUM_DRY_RUN = false (先设 true 可只看演练日志)
# 并在 Secrets 里配置 LDR_FORUM_API_KEY。
env:
LDR_FORUM_ENABLED: ${{ vars.LDR_FORUM_ENABLED || 'false' }}
LDR_FORUM_DRY_RUN: ${{ vars.LDR_FORUM_DRY_RUN || 'true' }}
LDR_FORUM_API_KEY: ${{ secrets.LDR_FORUM_API_KEY }}
LDR_FORUM_URL: ${{ vars.LDR_FORUM_URL || 'https://lowseek.ai' }}
LDR_FORUM_TAG_ID: ${{ vars.LDR_FORUM_TAG_ID || '21' }}
LDR_FORUM_MAX_PER_RUN: ${{ vars.LDR_FORUM_MAX_PER_RUN || '3' }}
LDR_FORUM_MAX_AGE_DAYS: ${{ vars.LDR_FORUM_MAX_AGE_DAYS || '3' }}
LDR_FORUM_MIN_PERCENT: ${{ vars.LDR_FORUM_MIN_PERCENT || '30' }}
# 读上一步生成的 deals.json,不重复抓取
run: python -m letdeals --forum-only
- name: Commit refreshed data
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add data/deals.json data/deals.md site/
# 注意:forum_posted.json 必须提交 —— 它是幂等依据,
# 丢了会导致同一活动被重复搬运到论坛。
git add data/deals.json data/deals.md site/ data/forum_posted.json
if git diff --staged --quiet; then
echo "无变化,跳过提交"
exit 0
@@ -97,7 +119,7 @@ jobs:
# 在其之上重新提交,从而始终是快进推送。
git fetch origin main
git reset --soft origin/main
git add data/deals.json data/deals.md site/
git add data/deals.json data/deals.md site/ data/forum_posted.json
if git diff --staged --quiet; then
echo "与远端一致,无需提交"
else
+45
View File
@@ -52,6 +52,8 @@ def build_parser() -> argparse.ArgumentParser:
# ---- 论坛发帖(旁路功能,默认关闭且默认演练)----
ap.add_argument("--post-forum", action="store_true",
help="把优惠帖搬运到论坛(需 LDR_FORUM_ENABLED=true)")
ap.add_argument("--forum-only", action="store_true",
help="只发帖:读现有 data/deals.json,不抓取也不建站")
ap.add_argument("--forum-dry-run", action="store_true",
help="演练:只打印将要发布的内容,不提交")
ap.add_argument("--forum-limit", type=int, default=0,
@@ -61,6 +63,43 @@ def build_parser() -> argparse.ArgumentParser:
return ap
def _forum_only(args, verbose: bool) -> int:
"""只发帖:读 data/deals.json,不抓取也不建站。"""
import json
from . import forum
path = args.json_out or str(config.DEALS_JSON)
if not os.path.exists(path):
print("!! 找不到 %s;请先运行一次抓取。" % path)
return 1
with open(path, encoding="utf-8") as f:
payload = json.load(f)
recs = payload.get("records") or []
if not recs:
print("!! %s 里没有记录。" % path)
return 1
if verbose:
print("=" * 72)
print("论坛发帖(只发帖模式)")
print("=" * 72)
print(" 数据来源:%s(%d 条)" % (path, len(recs)))
try:
forum.post_deals(
recs,
limit=args.forum_limit or None,
dry_run=True if args.forum_dry_run else None,
verbose=verbose,
)
except Exception as e: # 不让发帖失败影响整体
print(" !! 论坛发帖出错:%r" % e)
return 1
return 0
def main(argv: list[str] | None = None) -> int:
if hasattr(sys.stdout, "reconfigure"):
sys.stdout.reconfigure(encoding="utf-8")
@@ -68,6 +107,12 @@ def main(argv: list[str] | None = None) -> int:
args = build_parser().parse_args(argv)
verbose = not args.quiet
# ---- 只发帖模式:读现有 deals.json,不抓取也不建站 ----
# 用于把发帖与抓取解耦:工作流先更新数据并提交,
# 再由单独的步骤读同一份 JSON 发帖,避免重复抓取。
if args.forum_only:
return _forum_only(args, verbose)
sources = tuple(s.strip() for s in args.sources.split(",") if s.strip())
offline = {}
if args.offline_let: