diff --git a/docs/article-registry.json b/docs/article-registry.json index 6142e7a..7958130 100644 --- a/docs/article-registry.json +++ b/docs/article-registry.json @@ -1,5 +1,5 @@ { - "_generated": "2026-06-04T15:46:06.237Z", + "_generated": "2026-06-18T15:48:23.845Z", "_description": "Auto-generated from concepts.yaml + article frontmatter. LLM 生成文章時參考此檔案做跨文章連結。執行 node scripts/generate-article-registry.mjs 重新產生。", "concepts": { "OpenClaw": { @@ -182,6 +182,30 @@ "canonicalArticle": "pkm-system", "link": "/articles/pkm-system" }, + "Webhook": { + "displayName": "Webhook", + "shortDesc": "事件發生時由服務端主動把資料 POST 到你指定網址的回呼機制,Bot 即時收訊的基礎", + "canonicalArticle": "deploy-line-bot-cloudflare-workers", + "link": "/articles/deploy-line-bot-cloudflare-workers" + }, + "LINE Bot": { + "displayName": "LINE Bot", + "shortDesc": "透過 LINE 官方帳號的 Messaging API 接上後端,讓 LINE 帳號變成可自動回應的 AI 機器人", + "canonicalArticle": "deploy-line-bot-cloudflare-workers", + "link": "/articles/deploy-line-bot-cloudflare-workers" + }, + "Cloudflare Workers": { + "displayName": "Cloudflare Workers", + "shortDesc": "Cloudflare 的邊緣運算平台,部署即得 HTTPS 網址,免維護伺服器,適合當 Bot 後端", + "canonicalArticle": "deploy-line-bot-cloudflare-workers", + "link": "/articles/deploy-line-bot-cloudflare-workers" + }, + "wrangler": { + "displayName": "wrangler", + "shortDesc": "Cloudflare Workers 的命令列工具,負責登入、設定機密與一行指令部署", + "canonicalArticle": "deploy-line-bot-cloudflare-workers", + "link": "/articles/deploy-line-bot-cloudflare-workers" + }, "Zeabur": { "displayName": "Zeabur", "shortDesc": "台灣團隊打造的雲端部署平台,一鍵部署 OpenClaw", @@ -329,7 +353,9 @@ "Docker" ], "concepts_referenced": [ - "OpenClaw" + "OpenClaw", + "Cloudflare Workers", + "wrangler" ], "link": "/articles/deploy-openclaw-cloud" }, @@ -690,7 +716,9 @@ ], "concepts_referenced": [ "Harness", - "Telegram Bot" + "Telegram Bot", + "Webhook", + "LINE Bot" ], "link": "/articles/mcp-protocol" }, @@ -1014,6 +1042,32 @@ ], "link": "/articles/token-economics" }, + { + "slug": "deploy-line-bot-cloudflare-workers", + "title": "用 Cloudflare Workers 當 LINE Bot 後端:部署 Worker + 設定官方帳號 Webhook", + "description": "用 Claude Code 一行指令把 Cloudflare Worker 部署上線,再到 LINE 官方帳號後台開啟 Messaging API 與 Webhook,讓你的 LINE 帳號變成 24 小時在線的 AI 機器人。", + "scene": "整合與自動化", + "difficulty": "中級", + "contentType": "tutorial", + "tags": [ + "LINE", + "Cloudflare", + "Webhook", + "部署", + "整合" + ], + "prerequisites": [ + "telegram-integration" + ], + "concepts_defined": [ + "Webhook", + "LINE Bot", + "Cloudflare Workers", + "wrangler" + ], + "concepts_referenced": [], + "link": "/articles/deploy-line-bot-cloudflare-workers" + }, { "slug": "gemini-gas-ordering-system", "title": "用 Gemini 打造 AI 雲端訂餐系統:從菜單到廚房螢幕的 4 步驟實戰", @@ -1125,7 +1179,10 @@ "Telegram Bot" ], "concepts_referenced": [ - "MCP" + "MCP", + "Webhook", + "LINE Bot", + "Cloudflare Workers" ], "link": "/articles/telegram-integration" }, @@ -1194,7 +1251,7 @@ { "slug": "computex-2026-ai-era", "title": "Computex 2026:Nvidia 打破龍蝦瓶頸,個人 AI 助理元年正式開始", - "description": "四個月前我們在 LINE 群組預測:等技術成熟加上好用的地端模型,就是龍蝦普及的時刻。Computex 2026 的 Nvidia RTX Spark,讓這個預測提前兌現。", + "description": "四個月前我在課程中預測:等技術成熟加上好用的地端模型,就是龍蝦普及的時刻。Computex 2026 的 Nvidia RTX Spark,讓這個預測提前兌現,也將改變個人電腦的歷史。", "scene": "鴨編的碎碎念", "difficulty": "入門", "contentType": "guide", @@ -1340,6 +1397,7 @@ "Shell" ], "concepts_referenced": [ + "wrangler", "WSL", "Homebrew" ], diff --git a/docs/reverse-article-from-screenshots.md b/docs/reverse-article-from-screenshots.md new file mode 100644 index 0000000..a9b2c69 --- /dev/null +++ b/docs/reverse-article-from-screenshots.md @@ -0,0 +1,112 @@ +# 反向工作流程:從截圖反推教學文章 + +> 既有截圖 → 反推出一篇符合 LaunchDock 統一風格的文章。 +> 與正向流程(先寫文章帶 `@img` → 再截圖配對,見 `article-workflow-guide.md`)相反。 + +--- + +## 🔴 為什麼這件事必須在 Claude Code 做,不能在 cowork 做 + +1. **遮蔽是本機工具**:機敏資訊遮蔽靠 `auto-capture`(macOS Vision OCR,本機 Python),雲端的 cowork 跑不了。 +2. **順序問題**:一旦把**未遮蔽**的原始截圖上傳到雲端,機敏資訊在那一刻就已外流——遮蔽再好也來不及。**遮蔽必須在圖片離開機器之前、於本機完成。** +3. **風格一致性免費**:Claude Code 進 repo 自動讀 `CLAUDE.md`、`article-registry.json`、`concepts.yaml`,cowork 得手動貼且仍跑不了 `npm run registry`。 + +--- + +## ⚠️ 自動遮蔽的已知盲點(必讀) + +`auto-capture` 預設 regex 只抓:**信用卡 / API key(OpenAI/Anthropic/Google/AWS/GitHub)/ email / 通用 secret**。 + +**它「抓不到」**:用戶名、主機名、`/Users/...` 路徑、終端機提示字元(如 `joseph@MacBook`)、瀏覽器登入的個人名稱、人臉。 + +➡️ 所以一定要做 **AI 視覺第二輪**:人眼掃過每張圖,把上述個資用 `--mask-text` 指定 token,由 OCR 定位後整行馬賽克。 + +--- + +## 完整流程 + +### Step 0:環境(一次性) + +```bash +git clone https://github.com/589411/auto-capture.git ~/Documents/github/auto-capture +cd ~/Documents/github/auto-capture +python3 -m venv .venv && .venv/bin/pip install -e . +``` + +`scripts/redact-screenshots.py` 會在偵測不到套件時自動切換到這個 venv,所以平常用系統 `python3` 跑即可。 + +### Step 1:暫存原圖(先別進 `public/`) + +把要用的截圖複製到 `~/Desktop/captures/_staging//`,依操作順序命名 `01-raw.png`、`02-raw.png`…(`_staging` 與 `*-raw.png` 都不該被 commit)。 + +### Step 2:先掃描看哪裡有個資 + +```bash +python3 scripts/redact-screenshots.py ~/Desktop/captures/_staging/ --scan --suffix +``` + +讓 Claude Code 逐張看圖,列出**自動工具抓不到**的個資 token(用戶名、主機名等)。 + +### Step 3:兩輪遮蔽 + +```bash +# 預設 patterns + 人工 token,產出 NN-clean.png +python3 scripts/redact-screenshots.py ~/Desktop/captures/_staging/ \ + --suffix --mask-text joseph --mask-text MacBook +``` + +`--mask-text` 可重複,大小寫不拘;任何 OCR 文字行含該 token 就整行馬賽克。 + +### Step 4:上架前最終掃描(必須 0 命中) + +```bash +python3 scripts/redact-screenshots.py ~/Desktop/captures/_staging/ --scan --mask-text joseph +``` + +顯示「✅ 全部 clean」才能繼續。 + +### Step 5:複製乾淨圖進 `public/` + +用**語意化 kebab-case 檔名**(對應文章 @img 標記): + +```bash +DEST=public/images/articles/ +mkdir -p "$DEST" +cp ~/Desktop/captures/_staging//01-clean.png "$DEST/<描述性檔名>.png" +# …其餘類推 +``` + +### Step 6:反推文章(套統一風格) + +依 `CLAUDE.md` + `article-registry.json` + `concepts.yaml`: + +- 動筆前讀 registry,沿用既有概念用語、別重複解釋 +- 同步產出**中英文兩版**(`src/content/articles/.md`、`src/content/articles/en/.md`),scene/difficulty 用對應語言 key +- 完整 frontmatter;風格:繁中口語但專業、用「你」、步驟編號、常見錯誤用 `### 🚨` +- 圖片直接寫成已配對語法 `![alt](/images/articles//<檔名>.png)` + +### Step 7:新概念登錄 + +若引入 `concepts.yaml` 沒有的新名詞 → 補上,再跑: + +```bash +npm run registry +``` + +--- + +## 與正向流程的對照 + +| | 正向(既有) | 反向(本文) | +|---|---|---| +| 起點 | 先寫文章帶 `@img` 佔位 | 先有截圖 | +| 圖片 | 照標記去截圖、再配對 | 反推文字去對應既有圖 | +| 遮蔽 | 同樣必做 | 同樣必做(且更關鍵,個資已存在圖中) | +| 工具 | `scripts/add-image.sh` | `scripts/redact-screenshots.py` + 手動配對 | + +--- + +**首次實作產物**:`deploy-line-bot-cloudflare-workers`(中英文版)。 +**相關**:`article-workflow-guide.md`、`llm-article-prompt.md`、`image-workflow.md`、`CLAUDE.md`。 + +**Last updated:** 2026-06-18 diff --git a/public/images/articles/deploy-line-bot-cloudflare-workers/claude-code-deploy-worker.png b/public/images/articles/deploy-line-bot-cloudflare-workers/claude-code-deploy-worker.png new file mode 100644 index 0000000..1fedaf2 Binary files /dev/null and b/public/images/articles/deploy-line-bot-cloudflare-workers/claude-code-deploy-worker.png differ diff --git a/public/images/articles/deploy-line-bot-cloudflare-workers/line-disable-auto-reply.png b/public/images/articles/deploy-line-bot-cloudflare-workers/line-disable-auto-reply.png new file mode 100644 index 0000000..ac85329 Binary files /dev/null and b/public/images/articles/deploy-line-bot-cloudflare-workers/line-disable-auto-reply.png differ diff --git a/public/images/articles/deploy-line-bot-cloudflare-workers/line-messaging-api.png b/public/images/articles/deploy-line-bot-cloudflare-workers/line-messaging-api.png new file mode 100644 index 0000000..fcac14d Binary files /dev/null and b/public/images/articles/deploy-line-bot-cloudflare-workers/line-messaging-api.png differ diff --git a/public/images/articles/deploy-line-bot-cloudflare-workers/line-oa-group-invite.png b/public/images/articles/deploy-line-bot-cloudflare-workers/line-oa-group-invite.png new file mode 100644 index 0000000..83a060e Binary files /dev/null and b/public/images/articles/deploy-line-bot-cloudflare-workers/line-oa-group-invite.png differ diff --git a/public/images/articles/deploy-line-bot-cloudflare-workers/line-oa-home.png b/public/images/articles/deploy-line-bot-cloudflare-workers/line-oa-home.png new file mode 100644 index 0000000..80415c5 Binary files /dev/null and b/public/images/articles/deploy-line-bot-cloudflare-workers/line-oa-home.png differ diff --git a/public/images/articles/deploy-line-bot-cloudflare-workers/line-oa-webhook-toggle.png b/public/images/articles/deploy-line-bot-cloudflare-workers/line-oa-webhook-toggle.png new file mode 100644 index 0000000..5f1d7dd Binary files /dev/null and b/public/images/articles/deploy-line-bot-cloudflare-workers/line-oa-webhook-toggle.png differ diff --git a/scripts/redact-screenshots.py b/scripts/redact-screenshots.py new file mode 100755 index 0000000..14c6045 --- /dev/null +++ b/scripts/redact-screenshots.py @@ -0,0 +1,147 @@ +#!/usr/bin/env python3 +"""Redact sensitive info from a folder of screenshots (reverse-article workflow). + +Two-pass redaction, matching the LaunchDock security rule: + 1. auto-capture's default OCR patterns (credit cards / API keys / emails / secrets) + 2. AI-vision second pass: mask any OCR text line containing a personal token + you pass with --mask-text (usernames, hostnames, real names — the default + regexes DO NOT catch these). +Then a final scan reports whether the folder is clean. + +Usage: + # scan only (no changes), report what would be flagged + python3 scripts/redact-screenshots.py ~/Desktop/captures/_staging/ --scan + + # redact in place: default patterns + mask lines containing "joseph"/"MacBook" + python3 scripts/redact-screenshots.py ~/Desktop/captures/_staging/ \ + --mask-text joseph --mask-text MacBook + +Input images: /*.png (and .jpg/.jpeg). With --suffix, reads NN-raw.png and +writes NN-clean.png; otherwise edits files in place. + +Requires the auto-capture package (macOS Vision OCR). This script auto-re-execs +under ~/Documents/github/auto-capture/.venv if that venv exists. +""" +from __future__ import annotations + +import argparse +import os +import re +import shutil +import sys +from pathlib import Path + +AUTO_CAPTURE_DIR = Path.home() / "Documents/github/auto-capture" +VENV_PY = AUTO_CAPTURE_DIR / ".venv/bin/python" + + +def _ensure_deps(): + """Re-exec under the auto-capture venv if auto_capture isn't importable. + + Uses an env sentinel (not interpreter-path comparison) because on macOS a + venv built on the CommandLineTools python resolves to the same binary as + /usr/bin/python3, yet only the venv has the deps on its path. + """ + sys.path.insert(0, str(AUTO_CAPTURE_DIR)) + try: + import auto_capture.redact # noqa: F401 + return + except ImportError: + pass + if VENV_PY.exists() and not os.environ.get("_REDACT_REEXEC"): + os.environ["_REDACT_REEXEC"] = "1" + os.execv(str(VENV_PY), [str(VENV_PY), *sys.argv]) + sys.exit( + "❌ 找不到 auto-capture 套件。請先安裝:\n" + f" git clone https://github.com/589411/auto-capture.git {AUTO_CAPTURE_DIR}\n" + f" cd {AUTO_CAPTURE_DIR} && python3 -m venv .venv && .venv/bin/pip install -e ." + ) + + +def main() -> int: + _ensure_deps() + from auto_capture.redact import ( + _apply_mosaic, + _bbox_to_pixels, + _ocr_image, + SensitiveRegion, + redact_image, + ) + from auto_capture.config import DEFAULT_REDACT_PATTERNS, RedactConfig + from PIL import Image + + ap = argparse.ArgumentParser(description="Redact screenshots for LaunchDock articles") + ap.add_argument("dir", type=Path, help="folder of screenshots") + ap.add_argument("--mask-text", action="append", default=[], + help="personal token; any OCR line containing it gets mosaicked " + "(repeatable, case-insensitive)") + ap.add_argument("--scan", action="store_true", help="scan only, do not modify images") + ap.add_argument("--suffix", action="store_true", + help="read NN-raw.png, write NN-clean.png (default: edit in place)") + ap.add_argument("--block-size", type=int, default=14, help="mosaic block size") + args = ap.parse_args() + + stage: Path = args.dir + if not stage.is_dir(): + return print(f"❌ 找不到資料夾:{stage}") or 1 + + pat = "*-raw.png" if args.suffix else "*.png" + imgs = sorted(p for p in stage.glob(pat) + if "-clean" not in p.name) + \ + sorted(stage.glob("*.jpg")) + sorted(stage.glob("*.jpeg")) + if not imgs: + return print(f"❌ {stage} 內沒有圖片(pattern: {pat})") or 1 + + config = RedactConfig(enabled=True, block_size=args.block_size) + mask_tokens = [t.lower() for t in args.mask_text] + total = 0 + + print(f"{'🔍 掃描' if args.scan else '🔒 遮蔽'} {len(imgs)} 張圖片" + f"{'(含人工 token: ' + ', '.join(args.mask_text) + ')' if mask_tokens else ''}\n") + + for src in imgs: + dst = src.with_name(src.name.replace("-raw", "-clean")) if args.suffix else src + if not args.scan and args.suffix: + shutil.copy(src, dst) + + # Pass 1: default patterns (only writes when not --scan) + regions = [] + if not args.scan: + _, regions = redact_image(dst if args.suffix else src, config, + output_path=dst) + + # Pass 2: personal-token line masking + target = dst if (not args.scan and args.suffix) else src + ocr, (w, h) = _ocr_image(target) + line_hits = [] + if mask_tokens: + img = Image.open(target) + for r in ocr: + t = r["text"].lower() + if any(tok in t for tok in mask_tokens): + x, y, bw, bh = _bbox_to_pixels(r["bbox"], w, h, padding=6) + if bw > 0 and bh > 0: + line_hits.append(r["text"]) + if not args.scan: + _apply_mosaic(img, SensitiveRegion(x, y, bw, bh, + "personal_line", ""), args.block_size) + if not args.scan and line_hits: + img.save(target) + img.close() + + n = len(regions) + len(line_hits) + total += n + tag = "⚠️ " if (args.scan and n) else ("🔒" if n else "✅") + print(f"{tag} {src.name}: {n} 區" + + (f" {[r.pattern_name for r in regions] + line_hits}" if n else "")) + + print(f"\n📊 {'發現' if args.scan else '遮蔽'} {total} 個敏感區域,共 {len(imgs)} 張") + if args.scan and total: + print("➡️ 重跑時拿掉 --scan 即會實際遮蔽。") + elif not total: + print("✅ 全部 clean。") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/src/content/articles/deploy-line-bot-cloudflare-workers.md b/src/content/articles/deploy-line-bot-cloudflare-workers.md new file mode 100644 index 0000000..4a946ee --- /dev/null +++ b/src/content/articles/deploy-line-bot-cloudflare-workers.md @@ -0,0 +1,152 @@ +--- +title: "用 Cloudflare Workers 當 LINE Bot 後端:部署 Worker + 設定官方帳號 Webhook" +description: "用 Claude Code 一行指令把 Cloudflare Worker 部署上線,再到 LINE 官方帳號後台開啟 Messaging API 與 Webhook,讓你的 LINE 帳號變成 24 小時在線的 AI 機器人。" +contentType: "tutorial" +scene: "整合與自動化" +difficulty: "中級" +createdAt: "2026-06-18" +verifiedAt: "2026-06-18" +archived: false +order: 2 +prerequisites: ["telegram-integration"] +estimatedMinutes: 20 +tags: ["LINE", "Cloudflare", "Webhook", "部署", "整合"] +stuckOptions: + "為什麼選 Cloudflare Workers": ["跟自己架伺服器差在哪?", "免費額度夠用嗎?", "一定要會寫程式嗎?"] + "部署 Worker": ["wrangler 是什麼?", "deploy 後的網址在哪看?", "deploy 失敗怎麼辦?"] + "開啟 Messaging API": ["Channel secret 在哪複製?", "找不到 Messaging API 分頁", "Channel ID 跟 secret 差在哪?"] + "設定 Webhook": ["Webhook URL 要填哪一段?", "開了 Webhook 但 Bot 不回應", "驗證一直失敗"] + "常見問題排除": ["Bot 同時回兩則訊息", "訊息延遲很久", "改了程式要重新部署嗎?"] +--- + +## 為什麼用 Cloudflare Workers 當 LINE Bot 後端? + +要讓 LINE 官方帳號「會自己回話」,你需要一個 **24 小時在線、收到訊息就立刻處理的後端**。傳統做法是租一台雲端主機,但對個人或小專案來說又貴又難維護。 + +**Cloudflare Workers 把這件事變簡單:** + +| 比較項目 | Cloudflare Workers | 自架雲端主機 | +|---|---|---| +| 啟動速度 | 全球邊緣節點,毫秒級 | 要自己挑機房 | +| 費用 | 每天 10 萬次請求免費 | 最低也要月租 | +| 維護 | 不用管作業系統、不用更新 | 要自己顧 OS、安全性 | +| 部署 | 一行 `wrangler deploy` | SSH、設定一大堆 | +| 取得對外網址 | 部署完自動給你 HTTPS 網址 | 要自己設網域、憑證 | + +簡單說:你只要寫好處理訊息的程式,剩下「跑在哪、會不會掛、網址怎麼來」Cloudflare 都幫你搞定。這個對外的 HTTPS 網址,正是 LINE 用來推送訊息的 **Webhook URL**。 + +> 💡 如果你還沒用過 Bot Webhook 的概念,建議先看 [Telegram 整合完整教學](/articles/telegram-integration),那篇用更簡單的 BotFather 帶你跑過一次同樣的流程。 + +--- + +## 前置準備 + +開始前你需要: + +1. 一個 **LINE 官方帳號**(在 [LINE Official Account Manager](https://manager.line.biz) 免費建立) +2. 一個 **Cloudflare 帳號**(免費方案即可) +3. 本機裝好 **Claude Code** 與 **wrangler**(Cloudflare 的命令列部署工具) +4. 一份已經寫好的 Worker 程式(負責接收 LINE 訊息、呼叫 AI、回傳結果) + +整個流程分兩半:**先把後端部署上線拿到網址**,再**回 LINE 後台把網址貼上去並開啟 Webhook**。 + +--- + +## Step 1:用 Claude Code 部署 Cloudflare Worker + +在你的專案目錄打開 Claude Code,請它幫你完成 Cloudflare 的設定與部署。一個完整的部署通常包含這幾件事: + +1. `wrangler login`:登入你的 Cloudflare 帳號 +2. 設定 KV/R2 等儲存(如果你的 Bot 需要記住對話) +3. `wrangler secret put`:把 LINE 的 Channel secret 等機密以加密方式存進去(**不要寫在程式裡**) +4. `wrangler deploy`:部署上線,完成後它會回拋一個 **Webhook URL** + +![用 Claude Code 在專案目錄部署 Cloudflare Worker,準備設定 wrangler 與 LINE webhook](/images/articles/deploy-line-bot-cloudflare-workers/claude-code-deploy-worker.png) + +部署成功後,終端機會印出一個類似 `https://your-worker.xxx.workers.dev` 的網址。**把它記下來**,等一下要貼到 LINE 後台。 + +> ⚠️ Channel secret、access token 這類機密,一律用 `wrangler secret put` 存,不要 commit 進 Git。 + +--- + +## Step 2:進入 LINE 官方帳號後台 + +前往 [LINE Official Account Manager](https://manager.line.biz),登入後選擇你的官方帳號,進入主頁。右上角點「設定」。 + +![LINE 官方帳號管理後台主頁,右上角的設定入口](/images/articles/deploy-line-bot-cloudflare-workers/line-oa-home.png) + +--- + +## Step 3:開啟 Messaging API,取得 Channel 資訊 + +在設定頁左側選單找到 **Messaging API**。這裡有三項關鍵資訊: + +- **Channel ID**:頻道識別碼 +- **Channel secret**:用來驗證請求來源的密鑰(就是上一步要 `wrangler secret put` 存起來的) +- **Webhook URL**:填入 Step 1 拿到的 Worker 網址 + +![LINE Messaging API 設定頁,顯示 Channel ID、Channel secret 與 Webhook URL 欄位](/images/articles/deploy-line-bot-cloudflare-workers/line-messaging-api.png) + +把 **Webhook URL** 欄位填入你的 Worker 網址後按「儲存」。 + +> 🚨 **常見錯誤:secret 沒對上** +> 如果 Bot 收得到訊息卻一直回 401/驗證失敗,多半是後端存的 Channel secret 跟這裡顯示的不一致。回 Step 1 用 `wrangler secret put` 重存一次。 + +--- + +## Step 4:在「回應設定」開啟 Webhook + +光填網址還不夠,要告訴 LINE「訊息交給 Webhook 處理」。到「設定 → 回應設定」,這裡有幾個開關,照下圖設定: + +- **聊天**:關閉(不用真人客服聊天) +- **Webhook**:**開啟**(這是關鍵——開了 LINE 才會把訊息事件 POST 到你的 Worker) +- 自動回應訊息:可先保持開啟,下一步只關掉預設那則罐頭訊息 + +![回應設定頁面,聊天關閉、Webhook 開關已開啟](/images/articles/deploy-line-bot-cloudflare-workers/line-oa-webhook-toggle.png) + +> 💡 **(選用)讓 Bot 能被邀進群組**:在「帳號設定 → 功能切換」可勾選「接受邀請加入群組或多人聊天室」,之後就能把 Bot 拉進群組使用。 +> +> ![功能切換頁面,允許接受邀請加入群組](/images/articles/deploy-line-bot-cloudflare-workers/line-oa-group-invite.png) + +--- + +## Step 5:關閉預設自動回應訊息 + +LINE 預設會有一則「罐頭」自動回應,會跟你的 Bot 搶著回話,造成使用者收到兩則訊息。把它關掉。 + +在「自動回應訊息」把預設那則的開關關閉。 + +![自動回應訊息列表,將預設的自動回應開關關閉](/images/articles/deploy-line-bot-cloudflare-workers/line-disable-auto-reply.png) + +--- + +## 驗證結果 + +1. 用手機加入你的官方帳號為好友 +2. 隨便傳一則訊息 +3. 幾秒內收到由你的 Worker 處理後回傳的回應 —— 成功! + +如果沒反應,可以用 `wrangler tail` 即時查看 Worker 的日誌,看訊息有沒有進來、哪一步出錯。 + +--- + +## 常見問題 + +### 🚨 Bot 同時回兩則訊息 + +預設自動回應沒關(見 Step 5),或回應模式還停在「聊天」而不是 Webhook(見 Step 4)。 + +### 🚨 改了程式,LINE 上沒變化 + +Cloudflare Worker 不會自動更新,每次改完都要重新 `wrangler deploy`。Webhook URL 不變,不用回 LINE 後台重設。 + +### 🚨 收不到任何訊息 + +依序檢查:Webhook 開關有沒有開(Step 4)→ Webhook URL 有沒有填對且按了儲存(Step 3)→ 用 `wrangler tail` 看請求有沒有進到 Worker。 + +--- + +## 下一步 + +- 想讓 Bot 記住對話脈絡?了解 [AI Agent 的記憶機制](/articles/ai-agent-memory-guide) +- 想接更多服務(行事曆、資料庫、外部 API)?看 [MCP 協定](/articles/mcp-protocol) 怎麼把工具接給 AI diff --git a/src/content/articles/en/deploy-line-bot-cloudflare-workers.md b/src/content/articles/en/deploy-line-bot-cloudflare-workers.md new file mode 100644 index 0000000..6ab5175 --- /dev/null +++ b/src/content/articles/en/deploy-line-bot-cloudflare-workers.md @@ -0,0 +1,152 @@ +--- +title: "Run Your LINE Bot Backend on Cloudflare Workers: Deploy the Worker + Set Up the Official Account Webhook" +description: "Deploy a Cloudflare Worker with one Claude Code command, then enable the Messaging API and Webhook in the LINE Official Account console — turning your LINE account into a 24/7 AI bot." +contentType: "tutorial" +scene: "integration" +difficulty: "intermediate" +createdAt: "2026-06-18" +verifiedAt: "2026-06-18" +archived: false +order: 2 +prerequisites: ["telegram-integration"] +estimatedMinutes: 20 +tags: ["LINE", "Cloudflare", "Webhook", "Deploy", "Integration"] +stuckOptions: + "Why Cloudflare Workers": ["How is it different from running my own server?", "Is the free tier enough?", "Do I need to know how to code?"] + "Deploying the Worker": ["What is wrangler?", "Where do I find the URL after deploy?", "What if deploy fails?"] + "Enabling Messaging API": ["Where do I copy the Channel secret?", "Can't find the Messaging API tab", "What's the difference between Channel ID and secret?"] + "Setting up the Webhook": ["Which part goes in the Webhook URL?", "Webhook is on but the Bot doesn't respond", "Verification keeps failing"] + "Troubleshooting": ["Bot replies twice to one message", "Messages are heavily delayed", "Do I need to redeploy after editing code?"] +--- + +## Why Run Your LINE Bot Backend on Cloudflare Workers? + +To make a LINE Official Account "reply on its own," you need a backend that is **online 24/7 and processes messages the instant they arrive**. The traditional approach is renting a cloud server — but for individuals or small projects that's expensive and a hassle to maintain. + +**Cloudflare Workers makes this simple:** + +| Comparison | Cloudflare Workers | Self-hosted server | +|---|---|---| +| Startup speed | Global edge nodes, millisecond cold starts | Pick a data center yourself | +| Cost | 100k requests/day free | Monthly rent at minimum | +| Maintenance | No OS, no updates to manage | You manage the OS and security | +| Deploy | One `wrangler deploy` | SSH and a pile of config | +| Public URL | HTTPS URL auto-assigned on deploy | Set up your own domain & cert | + +In short: you only write the message-handling code; Cloudflare handles where it runs, whether it stays up, and the URL. That public HTTPS URL is exactly the **Webhook URL** LINE uses to push messages to you. + +> 💡 New to the Bot Webhook concept? Start with the [Telegram Integration Complete Guide](/en/articles/telegram-integration) — it walks you through the same flow with the simpler BotFather first. + +--- + +## Prerequisites + +Before you start you'll need: + +1. A **LINE Official Account** (create one free at [LINE Official Account Manager](https://manager.line.biz)) +2. A **Cloudflare account** (free plan is fine) +3. **Claude Code** and **wrangler** (Cloudflare's CLI deploy tool) installed locally +4. A Worker script already written (receives LINE messages, calls the AI, returns the result) + +The flow has two halves: **deploy the backend and get its URL**, then **go back to the LINE console to paste that URL in and turn on the Webhook**. + +--- + +## Step 1: Deploy the Cloudflare Worker with Claude Code + +Open Claude Code in your project directory and have it handle the Cloudflare setup and deploy. A complete deploy usually covers: + +1. `wrangler login`: log into your Cloudflare account +2. Set up KV / R2 storage (if your Bot needs to remember conversations) +3. `wrangler secret put`: store secrets like the LINE Channel secret encrypted (**never hardcode them**) +4. `wrangler deploy`: push it live — when done it returns a **Webhook URL** + +![Deploying a Cloudflare Worker with Claude Code in the project directory, setting up wrangler and the LINE webhook](/images/articles/deploy-line-bot-cloudflare-workers/claude-code-deploy-worker.png) + +After a successful deploy, the terminal prints a URL like `https://your-worker.xxx.workers.dev`. **Write it down** — you'll paste it into the LINE console shortly. + +> ⚠️ Secrets like the Channel secret and access token should always be stored with `wrangler secret put` — never commit them to Git. + +--- + +## Step 2: Open the LINE Official Account Console + +Go to [LINE Official Account Manager](https://manager.line.biz), log in, pick your official account, and land on the home page. Click "Settings" in the top right. + +![LINE Official Account Manager home page, with the Settings entry in the top right](/images/articles/deploy-line-bot-cloudflare-workers/line-oa-home.png) + +--- + +## Step 3: Enable the Messaging API and Grab the Channel Info + +In the left menu of the settings page, find **Messaging API**. Three key pieces of info live here: + +- **Channel ID**: the channel identifier +- **Channel secret**: the key used to verify request origin (the one you `wrangler secret put` in the previous step) +- **Webhook URL**: fill in the Worker URL from Step 1 + +![LINE Messaging API settings page showing Channel ID, Channel secret, and Webhook URL fields](/images/articles/deploy-line-bot-cloudflare-workers/line-messaging-api.png) + +Fill the **Webhook URL** field with your Worker URL and click Save. + +> 🚨 **Common mistake: the secret doesn't match** +> If the Bot receives messages but keeps returning 401 / verification failures, the Channel secret stored in your backend usually doesn't match the one shown here. Go back to Step 1 and re-store it with `wrangler secret put`. + +--- + +## Step 4: Turn On Webhook in "Response Settings" + +Filling in the URL isn't enough — you need to tell LINE to hand messages to the Webhook. Go to "Settings → Response settings." There are a few toggles here; set them like the screenshot below: + +- **Chat**: off (no live human chat) +- **Webhook**: **on** (this is the key — only then does LINE POST message events to your Worker) +- Auto-reply messages: leave it on for now; the next step only disables the default canned message + +![Response settings page with Chat off and the Webhook toggle enabled](/images/articles/deploy-line-bot-cloudflare-workers/line-oa-webhook-toggle.png) + +> 💡 **(Optional) Let the Bot be invited into groups**: under "Settings → Features," you can enable "Accept invitations to groups and multi-person chats" so you can later add the Bot to group chats. +> +> ![Features page, allowing the account to accept group invitations](/images/articles/deploy-line-bot-cloudflare-workers/line-oa-group-invite.png) + +--- + +## Step 5: Disable the Default Auto-Reply Message + +By default LINE has a canned auto-reply that competes with your Bot, so users get two messages. Turn it off. + +Under "Auto-reply messages," switch off the default one. + +![Auto-reply messages list, with the default auto-reply toggle switched off](/images/articles/deploy-line-bot-cloudflare-workers/line-disable-auto-reply.png) + +--- + +## Verify It Works + +1. Add your official account as a friend on your phone +2. Send any message +3. Within seconds you get a reply processed and returned by your Worker — success! + +If nothing happens, use `wrangler tail` to watch the Worker logs live and see whether messages are arriving and where it's failing. + +--- + +## Troubleshooting + +### 🚨 Bot replies twice to one message + +The default auto-reply isn't off (see Step 5), or the response mode is still on "Chat" instead of Webhook (see Step 4). + +### 🚨 Edited the code, but nothing changed on LINE + +Cloudflare Workers don't auto-update — run `wrangler deploy` again after every change. The Webhook URL stays the same, so no need to touch the LINE console. + +### 🚨 Receiving no messages at all + +Check in order: is the Webhook toggle on (Step 4) → is the Webhook URL filled in correctly and saved (Step 3) → use `wrangler tail` to see whether requests reach the Worker. + +--- + +## Next Steps + +- Want the Bot to remember conversation context? Learn about [how AI Agents handle memory](/en/articles/ai-agent-memory-guide) +- Want to connect more services (calendar, databases, external APIs)? See how [the MCP protocol](/en/articles/mcp-protocol) wires tools into the AI diff --git a/src/data/concepts.yaml b/src/data/concepts.yaml index b6dd136..d8e3cab 100644 --- a/src/data/concepts.yaml +++ b/src/data/concepts.yaml @@ -234,8 +234,36 @@ PKM: canonicalArticle: "pkm-system" relatedArticles: ["rag-explained", "openclaw-skill"] +Webhook: + displayName: "Webhook" + aliases: ["Webhook", "webhook", "Webhook URL"] + shortDesc: "事件發生時由服務端主動把資料 POST 到你指定網址的回呼機制,Bot 即時收訊的基礎" + canonicalArticle: "deploy-line-bot-cloudflare-workers" + relatedArticles: ["telegram-integration", "mcp-protocol"] + +LINE Bot: + displayName: "LINE Bot" + aliases: ["LINE Bot", "LINE bot", "LINE 機器人", "LINE 官方帳號", "Messaging API"] + shortDesc: "透過 LINE 官方帳號的 Messaging API 接上後端,讓 LINE 帳號變成可自動回應的 AI 機器人" + canonicalArticle: "deploy-line-bot-cloudflare-workers" + relatedArticles: ["telegram-integration", "mcp-protocol"] + # ── 部署與安裝 ────────────────────────────────────────── +Cloudflare Workers: + displayName: "Cloudflare Workers" + aliases: ["Cloudflare Workers", "Cloudflare Worker", "Workers", "Cloudflare"] + shortDesc: "Cloudflare 的邊緣運算平台,部署即得 HTTPS 網址,免維護伺服器,適合當 Bot 後端" + canonicalArticle: "deploy-line-bot-cloudflare-workers" + relatedArticles: ["deploy-openclaw-cloud", "telegram-integration"] + +wrangler: + displayName: "wrangler" + aliases: ["wrangler", "Wrangler"] + shortDesc: "Cloudflare Workers 的命令列工具,負責登入、設定機密與一行指令部署" + canonicalArticle: "deploy-line-bot-cloudflare-workers" + relatedArticles: ["cli-guide", "deploy-openclaw-cloud"] + Zeabur: displayName: "Zeabur" aliases: ["zeabur"]