
Research
Supply Chain Attack on Axios Pulls Malicious Dependency from npm
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.
@willh/fb-ad-blocker
Advanced tools
Intelligent Facebook spam detection and automation tool using Google Gemini AI and Playwright browser automation
這是一個智慧型 Facebook 垃圾留言偵測與自動化工具,使用 Google Gemini AI 來分析留言並自動處理垃圾內容。此工具可以自動偵測垃圾留言、刪除它們,並使用 Playwright 瀏覽器自動化來封鎖使用者。
blocked-pages.json,並同步維護純文字清單 blocked-pages.txt✨ 重構完成: 本專案已完成模組化重構,採用更清晰的分層架構。詳見下方「重構後的架構」章節。
fb-ad-blocker/
├── src/
│ ├── commands/ # CLI 命令入口點
│ │ ├── block-hidden-pages.js # 封鎖已隱藏留言者命令
│ │ ├── block-page.js # 封鎖頁面命令
│ │ └── hide-spam-comments.js # 隱藏垃圾留言命令
│ ├── core/ # 核心業務邏輯
│ │ ├── comment-processor.js # 留言處理器
│ │ └── page-blocker.js # 頁面封鎖處理器
│ ├── services/ # 外部服務整合
│ │ ├── browser.js # 瀏覽器服務
│ │ ├── gemini.js # Gemini API 服務
│ │ └── logger.js # 日誌服務
│ ├── utils/ # 工具函式
│ │ ├── blocked-pages.js # 封鎖記錄管理
│ │ ├── file-handler.js # 檔案讀寫操作
│ │ └── url-parser.js # URL 解析與處理
│ └── cli.js # CLI 主入口
├── examples/
│ ├── usage_example.js # 使用範例與功能展示
│ └── pages.txt # 範例封鎖頁面清單
├── test_gemini.js # 留言分析測試腳本
├── package.json # 專案相依性與腳本
├── .env.example # 環境配置範本
├── API.md # 詳細 API 文件
├── BLOCKED_PAGES.md # 封鎖記錄檔案格式說明
├── blocked-pages.json # 封鎖記錄(執行後自動產生/更新)
├── blocked-pages.txt # 被封鎖頁面 URL 純文字清單
├── analysis_results.json # 留言分析結果(執行後自動產生/更新)
├── storageState.json # 已登入會話狀態(您本機產生)
└── README.md # 本檔案
啟動 Playwright 容器
docker run --rm --name=fb-ad-blocker -it --entrypoint=bash mcr.microsoft.com/playwright:v1.55.1-noble
使用 Playwright 官方映像檔,就會內建所有必要的瀏覽器和相依性,免去安裝以下兩行命令:
npx -y playwright install-deps
npx -y playwright install chromium
安裝 npm 套件
npm install -g @willh/fb-ad-blocker
執行 fb-ad-blocker 以確認安裝成功
fb-ad-blocker -h
手動取得 FB 登入狀態檔 (storageState.json)
請利用 Chrome DevTools ➜ Playwright 工具,將登入狀態儲存到 storageState.json 檔案中,並放在目前目錄。
docker cp storageState.json fb-ad-blocker:/
驗證連線
export HEADLESS_MODE=1 # Linux 容器必須設定無頭模式
fb-ad-blocker test
設定環境變數
export GEMINI_API_KEY=your_api_key_here
export DRY_RUN=0
執行範例
export HEADLESS_MODE=1 # Linux 容器必須設定無頭模式
fb-ad-blocker hide-spam "https://www.facebook.com/will.fans/posts/pfbid0fCkVwz1e1QQKBFC2QJvtgGDSVicvVLLBqWdZ6RiwRtAP69JUcGpeQtSoxWwdFPmCl"
複製儲存庫
git clone https://github.com/doggy8088/fb-ad-blocker.git
cd fb-ad-blocker
安裝相依性
npm install
npm run install-browser
設定環境變數配置檔
cp .env.example .env
配置環境變數(編輯 .env 檔案):
# Google Gemini API 金鑰(從 https://aistudio.google.com/app/apikey 取得)
GEMINI_API_KEY=your_api_key_here
# 選用:指定 Gemini 模型
GEMINI_MODEL=gemini-2.5-pro
# 垃圾留言偵測配置
SPAM_ACTION=hide # 選項:hide, delete, report, none
SPAM_THRESHOLD=0.85 # 信心閾值(0.0 - 1.0)
DRY_RUN=0 # 設為 0 進行實際執行
# 瀏覽器執行模式(選用)
HEADLESS_MODE=0 # 1 或 true = 無頭模式;未設定/0/false = 顯示瀏覽器
# 針對 block-page 並行封鎖數(選用)
CONCURRENT_LIMIT=5 # 同時處理的頁面數;未設定則逐一處理
# Gemini 端點(選用)
# GEMINI_API_BASE=https://generativelanguage.googleapis.com
設定 Facebook 登入狀態(自動化所需)
storageState.json驗證連線
export HEADLESS_MODE=1 # Linux 容器必須設定無頭模式
npm run cli '--' test
測試留言分析功能而不進行 Facebook 自動化:
npm test
# 或
npm run analyze
這將分析範例留言並顯示分類結果。
您也可以執行綜合範例來查看所有功能:
npm run examples
這將展示:
範例輸出:
[
{
"comment": "很棒的貼文!謝謝分享。",
"label": "not_spam",
"confidence": 0.5,
"reason": "heuristic",
"raw": null
},
{
"comment": "🎉 免費賺錢 💰 立即點擊!🚀",
"label": "spam",
"confidence": 0.9,
"reason": "包含促銷語言和過多表情符號",
"raw": null
}
]
處理 Facebook 貼文並自動隱藏垃圾留言:
npm run cli -- hide-spam "https://www.facebook.com/posts/your-post-url"
# 或安裝為全域命令後
fb-ad-blocker hide-spam "https://www.facebook.com/posts/your-post-url"
這將會:
analysis_results.json處理已被粉絲專頁隱藏的留言,並封鎖發布者:
npm run cli -- block-hidden "https://www.facebook.com/posts/your-post-url"
# 或安裝為全域命令後
fb-ad-blocker block-hidden "https://www.facebook.com/posts/your-post-url"
這將會:
blocked-pages.json(包含頁面名稱、URL、留言內容等詳細資訊)blocked-pages.txt(僅 URL 清單,便於批次封鎖使用)📝 新功能:封鎖記錄追蹤
系統會自動記錄所有封鎖的頁面資訊到
blocked-pages.json檔案,包含:
- 封鎖日期和時間
- 被封鎖的頁面名稱和 URL
- 觸發封鎖的垃圾留言內容
- 封鎖理由
詳細格式請參考 BLOCKED_PAGES.md
提醒:即使在測試模式(
DRY_RUN=1)下,實際的「封鎖點擊」不會執行,但仍會將目標與理由寫入blocked-pages.json與blocked-pages.txt,方便後續人工/批次處理。
當需要一次處理多個貼文網址時,支援用 -f 指定一個文字檔,從檔案逐行讀取 URL:
npm run cli -- hide-spam -f posts.txt
# 或安裝為全域命令後
fb-ad-blocker hide-spam -f posts.txt
檔案格式說明:
範例 posts.txt(每行一個貼文網址):
https://www.facebook.com/<page>/posts/<post-id>
https://www.facebook.com/story.php?story_fbid=<id>&id=<id>
封鎖特定的 Facebook 專頁或個人檔案:
npm run cli -- block-page "https://www.facebook.com/profile-url" "https://www.facebook.com/another-profile"
# 或安裝為全域命令後
fb-ad-blocker block-page "https://www.facebook.com/profile-url"
同樣支援以 -f 從檔案讀取多個專頁/個人檔案網址:
npm run cli -- block-page -f examples/pages.txt
# 支援並行處理(-c 選項)
npm run cli -- block-page -c 3 -f blocked-pages.txt
# 或安裝為全域命令後
fb-ad-blocker block-page -c 5 -f examples/pages.txt
檔案格式說明:
blocked-pages.txt 作為輸入,或使用 examples/pages.txt並行處理:
CONCURRENT_LIMIT 控制同時封鎖處理的數量(僅 block-page 腳本適用)在您的程式碼中使用留言分析 API:
import { analyzeComments } from './src/gemini.js';
async function analyzeComment() {
const mainPost = "今天我要分享一些關於技術的想法...";
const comment = "很棒的貼文!非常有見地。";
const result = await analyzeComments(mainPost, comment, {
apiKeyEnv: 'GEMINI_API_KEY',
model: 'gemini-2.5-pro',
forceHeuristic: false // 設為 true 僅使用本地分析
});
console.log(result);
// {
// comment: "很棒的貼文!非常有見地。",
// label: "not_spam",
// confidence: 0.2,
// reason: "與相關內容的正面參與",
// raw: "..."
// }
}
import { analyzeComments } from './src/gemini.js';
async function processComments(mainPost, comments) {
const results = [];
for (const comment of comments) {
const result = await analyzeComments(mainPost, comment, {
apiKeyEnv: 'GEMINI_API_KEY'
});
results.push(result);
// 如果偵測到垃圾留言就處理
if (result.label === 'spam' && result.confidence > 0.85) {
console.log(`🚨 偵測到垃圾留言:${result.comment}`);
console.log(` 原因:${result.reason}`);
// 在此採取動作(刪除、檢舉等)
}
}
return results;
}
| 變數名稱 | 說明 | 預設值 | 選項 |
|---|---|---|---|
GEMINI_API_KEY | Google Gemini API 金鑰 | - | 從 AI Studio 取得 |
GEMINI_MODEL | 使用的 Gemini 模型 | gemini-2.5-pro | gemini-2.5-pro, gemini-1.5-flash |
SPAM_ACTION | 對垃圾留言採取的動作 | hide | delete, hide, report, none |
SPAM_THRESHOLD | 信心閾值 | 0.85 | 0.0 - 1.0 |
DRY_RUN | 測試模式(不執行實際動作) | 1 | 0(執行),1(僅測試) |
HEADLESS_MODE | 無頭模式開關 | 未設定(顯示瀏覽器) | 1/true(無頭),0/false(顯示) |
CONCURRENT_LIMIT | 封鎖專頁並行數(僅 block-page) | - | 正整數 |
GEMINI_API_BASE | Gemini 端點 | https://generativelanguage.googleapis.com | 自訂企業代理或官方端點 |
LOG_FILE_PATH | 日誌檔案路徑(選用) | - | 例如:./logs/fb-blocker.log |
AI 分類器會回傳以下其中一個標籤:
spam:明顯的促銷、無關或惡意內容possibly_spam:可疑內容,可能是垃圾留言not_spam:合法、相關的留言unsure:無法有信心地判斷delete:永久刪除垃圾留言hide:隱藏留言不讓公眾看見report:向 Facebook 檢舉留言none:僅偵測,不執行自動化動作本工具提供清晰易讀的增強式日誌輸出,包含以下特色:
設定 LOG_FILE_PATH 環境變數即可將日誌同時寫入檔案:
# 啟用檔案日誌
export LOG_FILE_PATH=./logs/fb-blocker.log
npm run hide-comments "https://facebook.com/post-url"
檔案日誌特色:
範例日誌輸出:
[2024/9/16 18:25:30.270] 🚀 開始處理 URL: https://facebook.com/post/123
[2024/9/16 18:25:30.487] 🌐 已導航到 URL
[2024/9/16 18:25:30.488] ✅ 成功取得留言: 15 個
[2024/9/16 18:25:30.489] 🔬 開始分析留言,使用 API: 是
[2024/9/16 18:25:30.490] 🚫 偵測到垃圾留言,準備採取動作
[2024/9/16 18:25:30.491] ⚡ 準備執行動作: delete
[2024/9/16 18:25:30.492] 🎉 處理完成
工具包含當沒有提供 API 金鑰時的備援啟發式分析:
// 增加垃圾留言機率的啟發式因子:
// - 包含 URL 或促銷語言
// - 過多表情符號或符號(3+ 個表情符號)
// - 促銷關鍵字(免費、折扣、點擊這裡等)
// - 重複標點符號或字元
// - 與主貼文內容高度相似
// - 重複詞彙且詞彙多樣性低
工具使用 Playwright 並採用以下預設設定:
const browser = await chromium.launch({
headless: process.env.HEADLESS_MODE === 'true' || process.env.HEADLESS_MODE === '1'
});
const context = await browser.newContext({
locale: 'zh-TW', // 支援繁體中文
storageState: 'storageState.json' // 已儲存的登入會話
});
工具包含全面的錯誤處理與記錄:
// 結果會自動儲存到 analysis_results.json
{
"mainPost": "原始貼文內容...",
"results": [
{
"comment": "留言文字...",
"label": "spam",
"confidence": 0.92,
"reason": "包含可疑連結的促銷內容",
"raw": "原始 API 回應..."
}
]
}
DRY_RUN=1 進行測試常見問題:
腳本完成後停在 Playwright 視窗:
page.pause() 以便人工檢視結果與除錯。請在 Playwright Inspector 按下繼續,或移除/註解該行以取消暫停。測試模式未實際封鎖但有記錄:
DRY_RUN=1 時不會對 UI 進行真實點擊封鎖,但仍會把候選目標寫入 blocked-pages.json 與 blocked-pages.txt,方便後續批次封鎖。"fetch is not a function" 錯誤
npm install node-fetch@3
Facebook 登入問題
storageState.json 存在且含有效會話API 驗證錯誤
GEMINI_API_KEY 是否正確瀏覽器自動化中找不到元素
headless: false 進行視覺化除錯要進行詳細除錯,請使用詳細記錄執行:
DEBUG=1 npm run cli -- hide-spam "your-facebook-url"
開啟 Google Chrome 瀏覽器
搜尋不想要的粉絲專頁
https://www.facebook.com/search/pages/?q=%E7%95%B6%E6%B2%96
進入粉絲專頁後,按下 F12 開啟開發者工具
直接執行以下腳本就可以順利複製出命令到剪貼簿:
const links = Array.from(
document.querySelectorAll('div[aria-label="搜尋結果"] a[href^="https://www.facebook.com/"]')
);
const cleanedHrefs = links.map(link => {
const url = new URL(link.href);
// 粉絲專頁:有 profile.php?id
if (url.pathname === '/profile.php' && url.searchParams.has('id')) {
return `https://www.facebook.com/profile.php?id=${url.searchParams.get('id')}`;
}
// 個人帳號:path 長度大於 1 且沒有 query string
if (url.pathname !== '/' && !url.search) {
return `https://www.facebook.com${url.pathname}`;
}
// 其他狀況(例如粉絲團短網址、含 query string 的動態頁)就忽略
return null;
}).filter(Boolean);
const uniqueHrefs = [...new Set(cleanedHrefs)];
const data = `npm run cli -- block-page ${uniqueHrefs.join(' ')}`;
copy(data);
也可以用 AI assistant 快速取得命令:
Find all the links that start with "https://www.facebook.com/profile.php?id=" and then merge them into the following string:
npm run cli -- block-page URL1 URL2 ...
Remove duplicated links.
執行命令
範例如下:
npm run cli -- block-page https://www.facebook.com/profile.php?id=100087996592961 https://www.facebook.com/dangchongxidangdie
本專案已完成模組化重構,採用清晰的分層架構,提升程式碼品質、可維護性和可擴展性。
src/
├── cli.js # CLI 主入口(使用 commander)
├── commands/ # 命令層 - CLI 命令入口點
│ ├── hide-spam-comments.js
│ ├── block-hidden-pages.js
│ └── block-page.js
├── core/ # 核心層 - 業務邏輯
│ ├── comment-processor.js
│ └── page-blocker.js
├── services/ # 服務層 - 外部服務整合
│ ├── browser.js
│ ├── gemini.js
│ └── logger.js
└── utils/ # 工具層 - 共用函式
├── url-parser.js
├── file-handler.js
└── blocked-pages.js
使用 commander 套件提供一致的命令列介面:
# 查看所有可用命令
npm run cli -- --help
# 隱藏垃圾留言
npm run cli -- hide-spam <url>
npm run cli -- hide-spam -f <file>
# 封鎖已被隱藏的留言者
npm run cli -- block-hidden <url>
# 封鎖頁面(支援並行處理)
npm run cli -- block-page <urls...>
npm run cli -- block-page -c 3 -f <file>
npm link
fb-ad-blocker --help
fb-ad-blocker hide-spam "https://facebook.com/post/123"
統一使用 CLI 介面執行各項功能:
# 隱藏垃圾留言
npm run cli -- hide-spam
# 封鎖已被隱藏的留言者
npm run cli -- block-hidden
# 封鎖頁面
npm run cli -- block-page
程式碼品質改進:
之前: 3 個主程式檔案(各約 300 行),utils.js 混合多種職責
之後: 清晰的分層架構,每個檔案平均約 150-200 行,單一職責原則
統一 CLI 介面
commander 提供專業的命令列體驗--help 查看詳細說明npm link)並行處理
block-page 命令支援 -c 選項控制並行數改進的錯誤處理
npm run cli -- hide-spam、npm run cli -- block-hidden、npm run cli -- block-pagenpm test、npm run examples、npm run analyze本專案使用 GitHub Actions 自動化 CI/CD 流程。
當程式碼推送到 main 分支時,會自動執行以下流程:
package.json 中的版本是否已存在於 npm registryv{version})更新版本號:
npm version patch # 1.0.0 -> 1.0.1(修補版本)
npm version minor # 1.0.0 -> 1.1.0(次要版本)
npm version major # 1.0.0 -> 2.0.0(主要版本)
提交並推送:
git add package.json package-lock.json
git commit -m "chore: bump version to x.x.x"
git push origin main
自動執行:GitHub Actions 會自動處理後續的發佈流程
詳細設定說明請參考 GitHub Actions 設定指南。
歡迎貢獻!請遵循以下步驟:
git checkout -b feature/amazing-feature
git commit -m "feat: 新增超棒的功能"
git push origin feature/amazing-feature
請使用 Conventional Commits 格式:
feat: 新增功能fix: 修正錯誤docs: 文件更新style: 程式碼格式調整refactor: 重構test: 測試相關chore: 建構流程或輔助工具變動所有 Pull Request 都會經過以下檢查:
MIT 授權 - 詳見 LICENSE 檔案
此工具僅供教育和合法內容管理用途。使用者需負責:
作者不對任何濫用或違反平台政策的行為負責。
FAQs
Intelligent Facebook spam detection and automation tool using Google Gemini AI and Playwright browser automation
The npm package @willh/fb-ad-blocker receives a total of 4 weekly downloads. As such, @willh/fb-ad-blocker popularity was classified as not popular.
We found that @willh/fb-ad-blocker demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.

Research
Malicious versions of the Telnyx Python SDK on PyPI delivered credential-stealing malware via a multi-stage supply chain attack.

Security News
TeamPCP is partnering with ransomware group Vect to turn open source supply chain attacks on tools like Trivy and LiteLLM into large-scale ransomware operations.