自製上市公司重訊追蹤器
這篇教學示範如何用一段 prompt 讓 AI agent(如 Claude Code)幫你建立一個「上市公司重訊追蹤器」,並在有新重訊時自動推播到你的 Slack。
這個追蹤器能做什麼
- 瀏覽上市/上櫃公司:搜尋公司名稱或股票代號,查看公司基本資訊
- 查看最新重訊:即時顯示任意公司的最新重大訊息(來源:公開資訊觀測站)
- 追蹤自選公司:把想關注的公司加入追蹤清單(存在瀏覽器,不需後端)
- 自動推播通知:網頁開著時,背景每 5 分鐘自動檢查追蹤公司有無新重訊,有新的就推播到你的 Slack
前置條件
在開始之前,請先完成以下設定:
- 歐噴資料庫帳號:到 data.openfun.tw 免費註冊
- 綁定 Slack 頻道:登入後到「個人頁面 → 推播設定」,完成 Slack 連結(否則通知無法送達)
- GitHub 帳號(選填):若想把追蹤器部署到 GitHub Pages,需要有帳號
使用方法
步驟一:開啟 Claude Code(或任何 AI coding agent)
步驟二:貼上以下 prompt
複製下方整段 prompt 貼給 AI agent,它會自動幫你完成所有程式碼:
請幫我建立一個「上市公司重訊追蹤器」純前端 web 服務(單一 index.html,無後端)。
## 資料來源
以下資料集說明和查詢方式請自行讀取 skill.md:
- 上市公司清單:https://data.openfun.tw/datasets/tw.com.twse~ref~listed/skill.md
- 上櫃公司清單:https://data.openfun.tw/datasets/tw.com.tpex~ref~otc/skill.md
- 重訊查詢(Elasticsearch):https://data.openfun.tw/datasets/tw.openfun~api~elastic-mopsov/skill.md
整體架構和 API 呼叫方式請參考:
https://data.openfun.tw/knowledge/build-openfun-web-service
## 登入與 Token 設計
使用 Device Authorization Grant 流程,申請具備以下 scope 的永久 token:
- requested_scopes: ["permanent", "notify"]
- requested_dataset_scope: ["tw.openfun~api~elastic-mopsov", "tw.com.twse~ref~listed", "tw.com.tpex~ref~otc"]
Token 存入 localStorage(key: openfun_token),需實作過期偵測(永久 token expires_in 為 null)。
注意:requested_dataset_scope 最多 3 個,此 tracker 剛好用完(elastic-mopsov、listed、otc);不需要 requested_category_scope。永久 token 鎖定後,只有這 3 個 dataset 可查,其他 dataset(含 public)均會被拒絕。
## 功能需求
### 1. 登入流程
- 頁面載入時檢查 localStorage 是否有有效 token
- 未登入時顯示登入按鈕,點擊後開啟 Device Auth 授權頁(verification_uri_complete)
- 在同分頁輪詢直到授權完成,無需開新視窗
### 2. 公司瀏覽與搜尋
- 搜尋框:可輸入公司名稱或股票代號(支援上市 + 上櫃);判斷輸入是否為 4 位數字,若是則用 `?公司代號=` 精確比對,否則用 `?q=` 全文搜尋
- 搜尋結果顯示:公司代號、公司名稱、產業別、市場別(上市/上櫃)
- 點擊公司 → 開啟公司詳情頁(或展開面板),顯示:
- 公司基本資訊(從 listed/otc 資料集取得)
- 最新 10 筆重訊(從 elastic-mopsov 取得,含主旨、時間、原始連結)
- 追蹤/取消追蹤按鈕(在搜尋結果和詳情頁均有)
### 3. 追蹤清單
- 首頁顯示目前追蹤的公司清單(從 localStorage 讀取)
- 每家公司顯示最新一筆重訊的主旨與時間
- 可從清單中移除追蹤
### 4. 背景輪詢與推播
- 登入後立即開始輪詢,間隔 5 分鐘
- 每次輪詢:對每家追蹤公司查詢 elastic-mopsov,取最新一筆的 spoke_at
- 若比上次記錄的 spoke_at 新 → 呼叫 POST /api/v1/notify 推播:
- message: "{公司名稱} 有新重訊:{公告主旨}"
- url: 該公告的 hyperlink
- digest: false(即時推播,若使用者為免費帳號改為 true)
- 輪詢狀態顯示在頁面角落(上次檢查時間)
### 5. 匯出/匯入追蹤清單
- 提供「匯出設定」按鈕,下載 JSON 檔(公司代號清單)
- 提供「匯入設定」按鈕,上傳 JSON 檔還原追蹤清單
## 技術要求
- 單一 index.html 檔,CSS 內嵌,無外部 CDN 依賴
- 支援 RWD(手機和桌面均可使用)
- 重訊查詢使用 Elasticsearch Query DSL(POST + JSON body),Base URL: https://elastic-mopsov.api.openfun.dev
- notify 失敗時(如 no_channel_bound、membership_required)要顯示友善的錯誤提示,不要 crash
- 頁籤在背景時降低輪詢頻率(15 分鐘)節省資源
## 完成後
程式碼完成後,詢問使用者:「這個追蹤器目前可以在本機瀏覽器直接開啟使用。如果你想部署到網路上讓其他人也能用,或是方便你在手機上存取,有幾種選項,需要我介紹嗎?」
若使用者想部署,請參考:https://data.openfun.tw/knowledge/deploy-static-web-service
步驟三:跟著 agent 完成授權設定
Agent 會:
- 產生
index.html程式碼 - 引導你在瀏覽器開啟並測試
- 說明如何部署到 GitHub Pages
首次使用追蹤器時,你需要完成歐噴帳號授權(選擇「永久授權」),之後不需要重複登入。
常見問題
Q:通知沒有送到 Slack?
A:確認已在歐噴個人頁面完成 Slack 綁定。若看到 no_channel_bound 錯誤,到 data.openfun.tw/user → 推播設定 → 連結 Slack。
Q:網頁關掉後還能收到通知嗎? A:不行。這個追蹤器使用瀏覽器端 JavaScript 輪詢,網頁關掉後就停止。若需要「關著也能收到通知」,需要搭配後端 cron job,超出純前端架構。
Q:追蹤的公司清單存在哪? A:存在瀏覽器的 localStorage,只有你自己的這台電腦這個瀏覽器看得到。可以用「匯出設定」備份,換電腦時用「匯入設定」還原。
Q:免費帳號可以用即時通知嗎?
A:免費帳號只能使用 digest 模式(彙整推播),即時推播需要付費帳號。Prompt 中的 digest: false 改成 digest: true 即可讓免費帳號也能使用(通知會延遲到下次 digest 批次送出)。
更多推播範例
熟悉上面的重訊追蹤器之後,同樣的做法(前置條件、使用步驟都一樣)也能套用到其他資料。以下兩個範例只要把步驟二的 prompt 換掉即可。
延伸範例一:政府新聞稿關鍵字追蹤器
這個追蹤器能做什麼
- 訂關鍵字:輸入想關注的詞(如「長照」「颱風」「電價」),可選擇只看某個機關、或只比對標題
- 看最新新聞稿:每個追蹤條件顯示最近 5 則符合的新聞稿(來源:中央五院、直轄市/縣市政府與部會所屬機關的新聞稿與公告)
- 自動推播通知:網頁開著時,每 5 分鐘檢查一次,有新的新聞稿就推播到你的 Slack
登入方式與重訊追蹤器不同
政府新聞稿資料集(tw.openfun~api~elastic-govnews)不能申請永久 token(device auth 帶 permanent 會回 400 只能限定公開資料集),所以這個追蹤器提供兩種登入:
- 歐噴帳號授權:24 小時有效,過期後按一次登入即可
- 貼上 API 金鑰:到 data.openfun.tw/user 申請長效金鑰貼進追蹤器,之後不用重新登入
Prompt
請幫我建立一個「政府新聞稿關鍵字追蹤器」純前端 web 服務(單一 index.html,無後端)。
## 資料來源
資料集說明和查詢方式請自行讀取 skill.md:
- 政府新聞稿搜尋(Elasticsearch):https://data.openfun.tw/datasets/tw.openfun~api~elastic-govnews/skill.md
- 收錄機關清單:https://data.openfun.tw/datasets/tw.openfun~ref~govnews-list/skill.md
整體架構和 API 呼叫方式請參考:
https://data.openfun.tw/knowledge/build-openfun-web-service
## 登入與 Token 設計
elastic-govnews 不是公開資料集,不能申請永久 token(device auth 帶 permanent + requested_dataset_scope 會回 400「只能限定公開資料集」)。請提供兩種登入方式:
1. Device Authorization Grant,只申請 requested_scopes: ["notify"](不要帶 permanent),token 24 小時有效
2. 讓使用者貼上自己在 data.openfun.tw/user 申請的 API 金鑰(長效)
Token 存入 localStorage(key: openfun_token),到期時間存 openfun_token_expires_at(API 金鑰存 "never")。ES 回 401 時清除 token 並提示重新登入。
## 功能需求
### 1. 追蹤條件
- 使用者輸入「關鍵字」(必填)、「機關」(選填)、「只比對標題」(勾選框)後加入追蹤
- 機關欄位提供下拉建議:用 ES terms aggregation 取 org_name.keyword 的所有值(size 2000)
- 查詢方式:bool.must 放 multi_match(type: "phrase"),fields 預設 ["title^3", "content_text"],勾「只比對標題」時改為 ["title"];有填機關時 bool.filter 加 term org_name.keyword
- 依 time 由新到舊排序,每次取 10 筆,_source 取 title、org_name、category、time、source_url
- 同一則新聞常以不同分類重複刊登(同機關同標題、不同 _id),請依「org_name + title」去重
### 2. 追蹤清單
- 顯示所有追蹤條件,每個條件列出最近 5 則(時間、機關、標題,標題連到 source_url)
- 可移除追蹤條件
### 3. 背景輪詢與推播
- 登入後立即檢查一次,之後每 5 分鐘一次;頁籤在背景時改為 15 分鐘
- 判斷「新的一則」請用 _id 比對(每個條件記住最近 100 個已看過的 _id),不要用 time 比大小:time 常只有日期(00:00:00),也有預排在未來時間的,用時間判斷會漏報或重複
- 某個條件第一次查詢時只建立基準、不推播
- 有新的就呼叫 POST https://data.openfun.tw/api/v1/notify:
- message: "【{關鍵字}|{機關}】{發布機關}:{標題}"
- url: source_url
- digest: 先送 false(即時);若回 membership_required 改送 true
- 頁面角落顯示上次檢查時間
### 4. 匯出/匯入
- 「匯出設定」下載 JSON(追蹤條件清單),「匯入設定」上傳 JSON 還原
## 技術要求
- 單一 index.html,CSS 內嵌,無外部 CDN 依賴,支援 RWD
- ES 端點:POST https://elastic-govnews.api.openfun.dev/gov-news_announcements/_search(Header: Authorization: Bearer {token})
- notify 失敗時(如 no_channel_bound、membership_required)要顯示友善的錯誤提示,不要 crash;錯誤碼在回應的 error 欄位
- 所有 localStorage 讀寫包 try/catch
## 完成後
程式碼完成後,詢問使用者:「這個追蹤器目前可以在本機瀏覽器直接開啟使用。如果你想部署到網路上讓其他人也能用,或是方便你在手機上存取,有幾種選項,需要我介紹嗎?」
若使用者想部署,請參考:https://data.openfun.tw/knowledge/deploy-static-web-service
延伸範例二:立法院委員會會議議程追蹤器
這個追蹤器能做什麼
- 勾選委員會:選你關心的常設委員會(內政、經濟、財政、教育及文化、交通、社福及衛環、外交及國防、司法及法制)
- 訂議程關鍵字:如「原子能法」「長照」,不分委員會,任何會議(含公聽會、黨團協商)的議程出現關鍵字就通知
- 看即將召開的會議:列出符合條件、日期在今天之後的會議,含時間、地點、會議事由
- 自動推播通知:新排會議、或已排會議的時間/地點/議程有異動時推播到你的 Slack
登入說明
立法院 API(tw.openfun~api~legislation)查資料不需要登入;登入只是為了推播,可以申請永久 token(鎖定 tw.openfun~api~legislation),之後不用重新登入。沒登入也能使用,只是不會推播。
Prompt
請幫我建立一個「立法院委員會會議議程追蹤器」純前端 web 服務(單一 index.html,無後端)。
## 資料來源
資料集說明和查詢方式請自行讀取 skill.md:
- 立法院 API(LYAPI):https://data.openfun.tw/datasets/tw.openfun~api~legislation/skill.md
整體架構、Device Auth 與 notify 呼叫方式請參考:
https://data.openfun.tw/knowledge/build-openfun-web-service
## 登入與 Token 設計
- 查立法院資料不需要 token。重要:從瀏覽器呼叫 https://ly.govapi.tw/v2 時「不要」帶 Authorization header,帶了會觸發 CORS preflight 而失敗(Failed to fetch);不帶 header 可正常取得資料
- token 只用在 notify 推播。使用 Device Authorization Grant 申請永久 token:
- requested_scopes: ["permanent", "notify"]
- requested_dataset_scope: ["tw.openfun~api~legislation"]
- Token 存入 localStorage(key: openfun_token),永久 token 的 expires_in 為 null
- 未登入時仍可瀏覽會議,只是不推播,頁首顯示「未登入:只顯示,不推播」
## 功能需求
### 1. 追蹤設定
- 委員會清單:GET /committees?limit=100,只列 委員會類別 = 1(常設委員會),以勾選框呈現,存 委員會代號
- 關鍵字:可新增/移除,比對「會議標題 + 會議資料[0].會議事由」(字串包含)
- 不要用 /meets 的 q 參數篩關鍵字:q 是模糊全文搜尋(實測 q=原子能法 回 7457 筆),請在前端自行比對
### 2. 取得會議
- GET /meets?limit=100(預設依 屆、會期、日期 由新到舊,已涵蓋即將召開與近期會議)
- 每筆會議取:會議代碼、會議種類、會議標題、日期(陣列)、委員會代號(陣列)、會議資料[0] 的 會議事由、會議時間區間、會議地點、ppg_url(公聽會可能沒有 ppg_url)
- 符合條件 = 委員會代號 有交集 或 關鍵字命中
- 「即將召開」區塊列出符合條件、最後一個日期 ≥ 今天(台灣時間)的會議,依日期排序,顯示日期、時間、地點、標題(有 ppg_url 就連過去)、符合原因、會議事由
### 3. 背景輪詢與推播
- 每 15 分鐘檢查一次,頁籤在背景時改為 60 分鐘
- 以 會議代碼 為 key,記錄每場會議的指紋(日期 + 會議時間區間 + 會議地點 + 會議事由)
- 沒看過的 會議代碼 → 推播「新排會議」
- 指紋改變 → 推播「議程異動」
- 第一次執行、以及使用者每次修改追蹤設定後的第一次檢查,只建立基準、不推播(避免把既有會議全部當成新會議)
- notify:POST https://data.openfun.tw/api/v1/notify
- message: "【立法院|{符合原因}】新排會議:{會議標題}({日期} {時間},{地點})" 或 "【立法院|{符合原因}】議程異動:{會議標題}({日期} {時間})"
- url: ppg_url(沒有就省略)
- digest: 先送 false;若回 membership_required 改送 true
### 4. 匯出/匯入
- 「匯出設定」下載 JSON(委員會代號與關鍵字),「匯入設定」上傳 JSON 還原
## 技術要求
- 單一 index.html,CSS 內嵌,無外部 CDN 依賴,支援 RWD
- notify 失敗時(如 no_channel_bound、membership_required)要顯示友善的錯誤提示,不要 crash;錯誤碼在回應的 error 欄位
- 所有 localStorage 讀寫包 try/catch
## 完成後
程式碼完成後,詢問使用者:「這個追蹤器目前可以在本機瀏覽器直接開啟使用。如果你想部署到網路上讓其他人也能用,或是方便你在手機上存取,有幾種選項,需要我介紹嗎?」
若使用者想部署,請參考:https://data.openfun.tw/knowledge/deploy-static-web-service
延伸範例常見問題
Q:政府新聞稿追蹤器每天都要重新登入? A:用歐噴帳號授權的話是(token 24 小時有效),因為這個資料集不支援永久授權。若不想每天登入,到 data.openfun.tw/user 申請 API 金鑰,貼進追蹤器即可。
Q:政府新聞稿追蹤器通知太多、有些不相關? A:關鍵字預設比對標題和內文,內文順帶提到也會命中。勾「只比對標題」或指定機關可以減少雜訊。
Q:立法院追蹤器為什麼沒有顯示即將召開的委員會會議? A:追蹤器只能顯示立法院已公布的排會。委員會通常在開會前幾天才公布議程;休會期間或新會期剛開始時,可能暫時沒有委員會會議。
有想法但不知道有什麼資料可以做?
如果你心裡有想追蹤的事情(例如「某個議題的政府公告」「某家公司有沒有被裁罰」「我家附近的標案」),但不確定歐噴資料庫有沒有對應的資料,可以直接跟 agent 討論,請它幫你盤點。把下面這段 prompt 貼給 agent,再把 {…} 換成你的想法:
我想做一個「有新資料就推播到 Slack」的純前端追蹤器,想追蹤的是:{用一兩句話描述你想追蹤什麼,例如:我關心的幾家公司有沒有新的裁罰、某個縣市有沒有新的標案}
請先不要寫程式,幫我盤點歐噴資料庫(data.openfun.tw)裡有沒有適合的資料。
## 盤點方式
1. 先引導我用 Device Authorization Grant 登入取得 token(流程見 https://data.openfun.tw/knowledge/build-openfun-web-service )
2. 用 GET https://data.openfun.tw/api/v1/search?q={關鍵字} 搜尋候選資料集;每個需求最多試 2 個關鍵字變體,找不到就直接告訴我「目前沒有對應資料集」,不要一直換關鍵字
3. 對每個候選資料集,讀它的 skill.md(https://data.openfun.tw/datasets/{slug}/skill.md),並實際打 API 確認以下幾點:
- 最新一筆資料的日期是什麼時候(資料有沒有在持續更新、大概多久更新一次)
- 能不能篩到我關心的對象(例如依公司、機關、關鍵字、地區篩選)
- 每筆資料有沒有穩定的 ID 可以判斷「這筆是新的」;如果只能靠日期,日期是不是精確到時間
- 從瀏覽器直接呼叫會不會被 CORS 擋(帶與不帶 Authorization header 都試試看)
- 能不能申請永久 token:用 device auth 帶 requested_scopes ["permanent","notify"] 和 requested_dataset_scope [slug] 試申請,回 400 就代表只能用 24 小時 token 或 API 金鑰
4. 整理成表格給我:資料集 slug、內容、最新一筆日期、可篩選的條件、判斷新資料的方式、CORS、能否永久 token,每項寫實測結果
5. 由我決定要用哪個資料集,確認後再照 https://data.openfun.tw/knowledge/mopsov-tracker-tutorial 裡的範例 prompt 格式幫我實作