w-dwdata-hub 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/README.md +16 -0
  2. package/dist/w-dwdata-hub.umd.js +2 -2
  3. package/dist/w-dwdata-hub.umd.js.map +1 -1
  4. package/docs/WDwdataHub.mjs.html +2 -2
  5. package/docs/decodeEntities.mjs.html +2 -2
  6. package/docs/extractDivContent.mjs.html +2 -2
  7. package/docs/fetchAiNewsAggregator.mjs.html +2 -2
  8. package/docs/fetchAisixiang.mjs.html +2 -2
  9. package/docs/fetchCnyes.mjs.html +2 -2
  10. package/docs/fetchGuancha.mjs.html +3 -7
  11. package/docs/fetchHackerNews.mjs.html +2 -2
  12. package/docs/fetchMoneydj.mjs.html +2 -2
  13. package/docs/fetchMops.mjs.html +2 -2
  14. package/docs/fetchRSS.mjs.html +106 -8
  15. package/docs/fetchStatementdog.mjs.html +2 -2
  16. package/docs/fetchTaifex.mjs.html +2 -2
  17. package/docs/fetchTpex3insti.mjs.html +2 -2
  18. package/docs/fetchTpexMargin.mjs.html +2 -2
  19. package/docs/fetchTpexStock.mjs.html +2 -2
  20. package/docs/fetchTwDataHoliday.mjs.html +2 -2
  21. package/docs/fetchTwseMargin.mjs.html +2 -2
  22. package/docs/fetchTwseStock.mjs.html +2 -2
  23. package/docs/fetchTwseT86.mjs.html +2 -2
  24. package/docs/fetchWithRetry.mjs.html +2 -2
  25. package/docs/getOptFetch.mjs.html +2 -2
  26. package/docs/global.html +807 -151
  27. package/docs/htmlToMarkdown.mjs.html +2 -2
  28. package/docs/index.html +2 -2
  29. package/docs/isYmd.mjs.html +2 -2
  30. package/docs/parseIntComma.mjs.html +2 -2
  31. package/docs/safeFilename.mjs.html +2 -2
  32. package/docs/stripHtml.mjs.html +130 -0
  33. package/docs/toDatetimeUTC8.mjs.html +26 -9
  34. package/docs/toRocDate.mjs.html +2 -2
  35. package/g.mjs +5 -0
  36. package/package.json +3 -3
  37. package/src/fetchGuancha.mjs +1 -5
  38. package/src/fetchRSS.mjs +104 -6
  39. package/src/stripHtml.mjs +58 -0
  40. package/src/toDatetimeUTC8.mjs +24 -7
  41. package/test/WDwdataHub.test.mjs +1 -1
  42. package/test/fetchRSS.test.mjs +78 -0
  43. package/test/stripHtml.test.mjs +58 -0
  44. package/test/toDatetimeUTC8.test.mjs +32 -0
  45. package/test/tools/fixtures.mjs +43 -0
  46. package/test/tools/serverForTest.mjs +12 -0
  47. package/toolg/gDistRollup.mjs +2 -2
package/README.md CHANGED
@@ -22,6 +22,7 @@ Note:
22
22
  - All fetch functions use node's built-in `fetch`, so node 18+ is required.
23
23
  - `fetchMops` needs Chrome installed (playwright uses `channel: 'chrome'`), or set env `CHROME_PATH` to the browser executable.
24
24
  - `fetchGuancha` delegates fetching to `w-fetch-web`, which needs `curl` in system PATH.
25
+ - `fetchRSS` with `opt.method` `'curl'` or `'auto'` also needs `curl` in system PATH.
25
26
 
26
27
  #### Functions:
27
28
 
@@ -79,6 +80,11 @@ let test = async () => {
79
80
  console.log('rss:', r1.length, r1[0].time, r1[0].title)
80
81
  // => rss: 19 2026-08-07 09:30:19 [問卦] 公視是怎麼走到今天這一步的?
81
82
 
83
+ //綜合新聞: 擋node fetch之站台(403)改走curl抓取, 並以withContent附feed內嵌全文(去標籤純文字)
84
+ let r1b = await wi.fetchRSS('https://alphaarchitect.com/feed', { method: 'curl', withContent: true, showLog: false })
85
+ console.log('rss(curl):', r1b.length, r1b[0].content.length, r1b[0].description.length)
86
+ // => rss(curl): 5 6339 545
87
+
82
88
  //綜合新聞: Hacker News最新文章, 可指定取回篇數
83
89
  let r2 = await wi.fetchHackerNews(5, { showLog: false })
84
90
  console.log('hackerNews:', r2.length, r2[0].from, r2[0].title)
@@ -155,6 +161,16 @@ await test()
155
161
 
156
162
  重試條件為HTTP 5xx與429及網路層錯誤(含逾時);HTTP 4xx(429除外)預設不重試,僅部份函數另納入403或404(例如鉅亨網、財報狗、MoneyDJ納入403,RSS納入404)。
157
163
 
164
+ #### Options for fetchRSS:
165
+ `fetchRSS`另有專屬選項:
166
+
167
+ | key | type | default | description |
168
+ | --- | --- | --- | --- |
169
+ | `method` | String | `'fetch'` | 抓取方式,可為`'fetch'`(node內建fetch)、`'curl'`(系統curl,可通過以TLS指紋擋非瀏覽器用戶端之站台)、`'auto'`(curl優先,失敗退回fetch) |
170
+ | `withContent` | Boolean | `false` | `true`時各項目附加`content`欄,依`content:encoded`→`content`→`summary`→`description`優先序取feed內嵌全文,並去除HTML標籤與實體、保留段落換行 |
171
+
172
+ curl模式之重試退避由`w-fetch-web`內建(3至15秒線性),`baseDelayMs`/`maxDelayMs`/404重試於curl模式不生效;極短之feed(小於100字元)會被curl模式判為`empty-response`。
173
+
158
174
  #### Error contract:
159
175
  - 參數不合法(如日期非`YYYYMMDD`、必填參數缺漏)一律`throw`,不會靜默回傳空結果。
160
176
  - 抓取或解析失敗一律`reject`;`fetchAisixiang`與`fetchGuancha`則改回傳`{status:'error',...}`結果物件。
@@ -1,7 +1,7 @@
1
1
  /*!
2
- * w-dwdata-hub v1.0.1
2
+ * w-dwdata-hub v1.0.3
3
3
  * (c) 2018-2021 yuda-lyu(semisphere)
4
4
  * Released under the MIT License.
5
5
  */
6
- !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e(require("w-fetch-web"),require("cheerio"),require("playwright"),require("rss-parser")):"function"==typeof define&&define.amd?define(["w-fetch-web","cheerio","playwright","rss-parser"],e):(t="undefined"!=typeof globalThis?globalThis:t||self)["w-dwdata-hub"]=e(t["w-fetch-web"],t.cheerio,t.playwright,t["rss-parser"])}(this,function(t,e,r,n){"use strict";function a(t){var e=Object.create(null);return t&&Object.keys(t).forEach(function(r){if("default"!==r){var n=Object.getOwnPropertyDescriptor(t,r);Object.defineProperty(e,r,n.get?n:{enumerable:!0,get:function(){return t[r]}})}}),e.default=t,Object.freeze(e)}var s=a(e),i=Array.isArray,o="object"==typeof global&&global&&global.Object===Object&&global,l="object"==typeof self&&self&&self.Object===Object&&self,u=o||l||Function("return this")(),c=u.Symbol,h=Object.prototype,f=h.hasOwnProperty,g=h.toString,d=c?c.toStringTag:void 0;var m=Object.prototype.toString;var p=c?c.toStringTag:void 0;function w(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":p&&p in Object(t)?function(t){var e=f.call(t,d),r=t[d];try{t[d]=void 0;var n=!0}catch(t){}var a=g.call(t);return n&&(e?t[d]=r:delete t[d]),a}(t):function(t){return m.call(t)}(t)}function y(t){return null!=t&&"object"==typeof t}function $(t){return"symbol"==typeof t||y(t)&&"[object Symbol]"==w(t)}var b=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,S=/^\w*$/;function _(t){var e=typeof t;return null!=t&&("object"==e||"function"==e)}var v,D=u["__core-js_shared__"],M=(v=/[^.]+$/.exec(D&&D.keys&&D.keys.IE_PROTO||""))?"Symbol(src)_1."+v:"";var A=Function.prototype.toString;var x=/^\[object .+?Constructor\]$/,T=Function.prototype,E=Object.prototype,O=T.toString,k=E.hasOwnProperty,j=RegExp("^"+O.call(k).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function L(t){if(!_(t)||(e=t,M&&M in e))return!1;var e,r=function(t){if(!_(t))return!1;var e=w(t);return"[object Function]"==e||"[object GeneratorFunction]"==e||"[object AsyncFunction]"==e||"[object Proxy]"==e}(t)?j:x;return r.test(function(t){if(null!=t){try{return A.call(t)}catch(t){}try{return t+""}catch(t){}}return""}(t))}function P(t,e){var r=function(t,e){return null==t?void 0:t[e]}(t,e);return L(r)?r:void 0}var C=P(Object,"create");var I=Object.prototype.hasOwnProperty;var U=Object.prototype.hasOwnProperty;function R(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e<r;){var n=t[e];this.set(n[0],n[1])}}function Y(t,e){return t===e||t!=t&&e!=e}function N(t,e){for(var r=t.length;r--;)if(Y(t[r][0],e))return r;return-1}R.prototype.clear=function(){this.__data__=C?C(null):{},this.size=0},R.prototype.delete=function(t){var e=this.has(t)&&delete this.__data__[t];return this.size-=e?1:0,e},R.prototype.get=function(t){var e=this.__data__;if(C){var r=e[t];return"__lodash_hash_undefined__"===r?void 0:r}return I.call(e,t)?e[t]:void 0},R.prototype.has=function(t){var e=this.__data__;return C?void 0!==e[t]:U.call(e,t)},R.prototype.set=function(t,e){var r=this.__data__;return this.size+=this.has(t)?0:1,r[t]=C&&void 0===e?"__lodash_hash_undefined__":e,this};var F=Array.prototype.splice;function H(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e<r;){var n=t[e];this.set(n[0],n[1])}}H.prototype.clear=function(){this.__data__=[],this.size=0},H.prototype.delete=function(t){var e=this.__data__,r=N(e,t);return!(r<0)&&(r==e.length-1?e.pop():F.call(e,r,1),--this.size,!0)},H.prototype.get=function(t){var e=this.__data__,r=N(e,t);return r<0?void 0:e[r][1]},H.prototype.has=function(t){return N(this.__data__,t)>-1},H.prototype.set=function(t,e){var r=this.__data__,n=N(r,t);return n<0?(++this.size,r.push([t,e])):r[n][1]=e,this};var q=P(u,"Map");function z(t,e){var r,n,a=t.__data__;return("string"==(n=typeof(r=e))||"number"==n||"symbol"==n||"boolean"==n?"__proto__"!==r:null===r)?a["string"==typeof e?"string":"hash"]:a.map}function W(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e<r;){var n=t[e];this.set(n[0],n[1])}}W.prototype.clear=function(){this.size=0,this.__data__={hash:new R,map:new(q||H),string:new R}},W.prototype.delete=function(t){var e=z(this,t).delete(t);return this.size-=e?1:0,e},W.prototype.get=function(t){return z(this,t).get(t)},W.prototype.has=function(t){return z(this,t).has(t)},W.prototype.set=function(t,e){var r=z(this,t),n=r.size;return r.set(t,e),this.size+=r.size==n?0:1,this};function B(t,e){if("function"!=typeof t||null!=e&&"function"!=typeof e)throw new TypeError("Expected a function");var r=function(){var n=arguments,a=e?e.apply(this,n):n[0],s=r.cache;if(s.has(a))return s.get(a);var i=t.apply(this,n);return r.cache=s.set(a,i)||s,i};return r.cache=new(B.Cache||W),r}B.Cache=W;var K,G,X,Z=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,J=/\\(\\)?/g,V=(K=function(t){var e=[];return 46===t.charCodeAt(0)&&e.push(""),t.replace(Z,function(t,r,n,a){e.push(n?a.replace(J,"$1"):r||t)}),e},G=B(K,function(t){return 500===X.size&&X.clear(),t}),X=G.cache,G),Q=V;var tt=c?c.prototype:void 0,et=tt?tt.toString:void 0;function rt(t){if("string"==typeof t)return t;if(i(t))return function(t,e){for(var r=-1,n=null==t?0:t.length,a=Array(n);++r<n;)a[r]=e(t[r],r,t);return a}(t,rt)+"";if($(t))return et?et.call(t):"";var e=t+"";return"0"==e&&1/t==-1/0?"-0":e}function nt(t){return null==t?"":rt(t)}function at(t,e){return i(t)?t:function(t,e){if(i(t))return!1;var r=typeof t;return!("number"!=r&&"symbol"!=r&&"boolean"!=r&&null!=t&&!$(t))||S.test(t)||!b.test(t)||null!=e&&t in Object(e)}(t,e)?[t]:Q(nt(t))}function st(t){if("string"==typeof t||$(t))return t;var e=t+"";return"0"==e&&1/t==-1/0?"-0":e}function it(t,e,r){var n=null==t?void 0:function(t,e){for(var r=0,n=(e=at(e,t)).length;null!=t&&r<n;)t=t[st(e[r++])];return r&&r==n?t:void 0}(t,e);return void 0===n?r:n}function ot(t){return"[object String]"===Object.prototype.toString.call(t)}function lt(t){return!(!ot(t)||""===t)}function ut(t){return"[object Array]"===Object.prototype.toString.call(t)}function ct(t){return"[object Object]"===Object.prototype.toString.call(t)}function ht(t){return t!=t}function ft(t){return!!function(t){return"[object Undefined]"===Object.prototype.toString.call(t)}(t)||(!!function(t){return"[object Null]"===Object.prototype.toString.call(t)}(t)||(!!function(t){if(ct(t)){for(let e in t)return!1;return!0}return!1}(t)||(!!function(t){return!(!ot(t)||""!==t)}(t)||(!!function(t){return!!ut(t)&&0===t.length}(t)||!!ht(t)))))}function gt(t){return!!ut(t)&&(0!==t.length&&(1!==t.length||!ft(t[0])))}function dt(t){return!0===(e=t)||!1===e||y(e)&&"[object Boolean]"==w(e);var e}var mt=/\s/;var pt=/^\s+/;function wt(t){return t?t.slice(0,function(t){for(var e=t.length;e--&&mt.test(t.charAt(e)););return e}(t)+1).replace(pt,""):t}var yt=/^[-+]0x[0-9a-f]+$/i,$t=/^0b[01]+$/i,bt=/^0o[0-7]+$/i,St=parseInt;function _t(t){if("number"==typeof t)return t;if($(t))return NaN;if(_(t)){var e="function"==typeof t.valueOf?t.valueOf():t;t=_(e)?e+"":e}if("string"!=typeof t)return 0===t?t:+t;t=wt(t);var r=$t.test(t);return r||bt.test(t)?St(t.slice(2),r?2:8):yt.test(t)?NaN:+t}var vt=1/0;function Dt(t){return t?(t=_t(t))===vt||t===-1/0?17976931348623157e292*(t<0?-1:1):t==t?t:0:0===t?t:0}function Mt(t){var e=Dt(t),r=e%1;return e==e?r?e-r:e:0}function At(t){let e=!1;if(lt(t))e=!isNaN(Number(t));else if(function(t){return"[object Number]"===Object.prototype.toString.call(t)}(t)){if(ht(t))return!1;e=!0}return e}function xt(t){if(!At(t))return 0;return Dt(t)}function Tt(t){return!!At(t)&&(t=xt(t),"number"==typeof(e=t)&&e==Mt(e));var e}var Et=u.isFinite,Ot=Math.min;var kt=function(t){var e=Math[t];return function(t,r){if(t=_t(t),(r=null==r?0:Ot(Mt(r),292))&&Et(t)){var n=(nt(t)+"e").split("e");return+((n=(nt(e(n[0]+"e"+(+n[1]+r)))+"e").split("e"))[0]+"e"+(+n[1]-r))}return e(t)}}("round"),jt=kt;function Lt(t){if(!At(t))return 0;t=xt(t);let e=jt(t);return"0"===String(e)?0:e}function Pt(t){if(!Tt(t))return!1;return Lt(t)>0}function Ct(t){if(!Tt(t))return!1;return Lt(t)>=0}function It(t=10){At(t)||(t=10);let e=function(){let t,e,r=new Promise(function(){t=arguments[0],e=arguments[1]});return r.resolve=t,r.reject=e,r}();return setTimeout(function(){e.resolve()},t),e}let Ut=["ECONNRESET","ETIMEDOUT","ENOTFOUND","ECONNREFUSED","ECONNABORTED","EAI_AGAIN","EPIPE"];function Rt(t,e){let r=it(t,"statusCode",null);if(Pt(r))return r>=500||429===r||e.includes(r);let n=it(t,"cause.code",null)||it(t,"code",null);if(lt(n)&&Ut.includes(n))return!0;let a=it(t,"name","");if("AbortError"===a||"TimeoutError"===a)return!0;let s=String(it(t,"cause.code","")||it(t,"message",""));return!!/UND_ERR_(SOCKET|HEADERS_TIMEOUT|BODY_TIMEOUT|CONNECT_TIMEOUT)/.test(s)}async function Yt(t,e){let r=new AbortController,n=setTimeout(()=>{r.abort()},e.timeout);try{let n={method:e.method,headers:e.headers,signal:r.signal};null!==e.body&&(n.body=e.body);let a=await fetch(t,n);if(!a.ok){let e=new Error(`HTTP ${a.status} ${a.statusText}`.trim());throw e.statusCode=a.status,e.url=t,e}if("arrayBuffer"===e.responseType)return await a.arrayBuffer();if("text"===e.responseType){if(""!==e.encoding){let t=await a.arrayBuffer();return new TextDecoder(e.encoding).decode(t)}return await a.text()}let s=await a.text();try{return JSON.parse(s)}catch(t){throw new Error(`回傳非JSON格式(可能為維護頁面或網路中介): ${s.slice(0,100)}`)}}finally{clearTimeout(n)}}async function Nt(t,e={}){if(!lt(t))throw new Error(`url須為有效字串, 得到: ${t}`);let r=it(e,"method");lt(r)||(r="GET");let n=it(e,"headers");ct(n)||(n={}),lt(it(n,"User-Agent"))||(n={"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",...n});let a=it(e,"body",null);lt(a)||(a=null);let s=it(e,"responseType");"text"!==s&&"arrayBuffer"!==s&&(s="json");let i=it(e,"encoding");lt(i)||(i="");let o=it(e,"timeout");o=Pt(o)?Lt(o):3e4;let l=it(e,"maxRetries");l=Ct(l)?Lt(l):10;let u=it(e,"baseDelayMs");u=Pt(u)?Lt(u):5e3;let c=it(e,"maxDelayMs");c=Pt(c)?Lt(c):3e4;let h=it(e,"retryStatus");gt(h)||(h=[]);let f=it(e,"label");lt(f)||(f="fetchWithRetry");let g=it(e,"showLog");dt(g)||(g=!0);let d={method:r,headers:n,body:a,responseType:s,encoding:i,timeout:o},m=null;for(let e=1;e<=l+1;e++)try{return await Yt(t,d)}catch(t){m=t;let r=l+1-e;if(!Rt(t,h)||r<=0)throw t;let n=Math.min(u*e,c);g&&console.warn(`[${f}][Retry ${e}/${l}] ${t.message} — 等待 ${n/1e3}s 後重試...`),await It(n)}throw m}function Ft(t,e,r,n){let a=it(t,r);return Pt(a)?Lt(a):(a=it(e,r),Pt(a)?Lt(a):n)}function Ht(t={},e={}){let r=it(t,"maxRetries");Ct(r)||(r=it(e,"maxRetries")),r=Ct(r)?Lt(r):10;let n=it(t,"showLog");dt(n)||(n=it(e,"showLog")),dt(n)||(n=!0);let a={timeout:Ft(t,e,"timeout",3e4),maxRetries:r,baseDelayMs:Ft(t,e,"baseDelayMs",5e3),maxDelayMs:Ft(t,e,"maxDelayMs",3e4),showLog:n};return lt(it(e,"responseType"))&&(a.responseType=e.responseType),lt(it(e,"encoding"))&&(a.encoding=e.encoding),ct(it(e,"headers"))&&(a.headers=e.headers),gt(it(e,"retryStatus"))&&(a.retryStatus=e.retryStatus),lt(it(e,"label"))&&(a.label=e.label),a}"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self&&self;function qt(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var zt={exports:{}};!function(t){t.exports=function(){var t=1e3,e=6e4,r=36e5,n="millisecond",a="second",s="minute",i="hour",o="day",l="week",u="month",c="quarter",h="year",f="date",g="Invalid Date",d=/^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[Tt\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/,m=/\[([^\]]+)]|YYYY|YY|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g,p={name:"en",weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),ordinal:function(t){var e=["th","st","nd","rd"],r=t%100;return"["+t+(e[(r-20)%10]||e[r]||e[0])+"]"}},w=function(t,e,r){var n=String(t);return!n||n.length>=e?t:""+Array(e+1-n.length).join(r)+t},y={s:w,z:function(t){var e=-t.utcOffset(),r=Math.abs(e),n=Math.floor(r/60),a=r%60;return(e<=0?"+":"-")+w(n,2,"0")+":"+w(a,2,"0")},m:function t(e,r){if(e.date()<r.date())return-t(r,e);var n=12*(r.year()-e.year())+(r.month()-e.month()),a=e.clone().add(n,u),s=r-a<0,i=e.clone().add(n+(s?-1:1),u);return+(-(n+(r-a)/(s?a-i:i-a))||0)},a:function(t){return t<0?Math.ceil(t)||0:Math.floor(t)},p:function(t){return{M:u,y:h,w:l,d:o,D:f,h:i,m:s,s:a,ms:n,Q:c}[t]||String(t||"").toLowerCase().replace(/s$/,"")},u:function(t){return void 0===t}},$="en",b={};b[$]=p;var S="$isDayjsObject",_=function(t){return t instanceof A||!(!t||!t[S])},v=function t(e,r,n){var a;if(!e)return $;if("string"==typeof e){var s=e.toLowerCase();b[s]&&(a=s),r&&(b[s]=r,a=s);var i=e.split("-");if(!a&&i.length>1)return t(i[0])}else{var o=e.name;b[o]=e,a=o}return!n&&a&&($=a),a||!n&&$},D=function(t,e){if(_(t))return t.clone();var r="object"==typeof e?e:{};return r.date=t,r.args=arguments,new A(r)},M=y;M.l=v,M.i=_,M.w=function(t,e){return D(t,{locale:e.$L,utc:e.$u,x:e.$x,$offset:e.$offset})};var A=function(){function p(t){this.$L=v(t.locale,null,!0),this.parse(t),this.$x=this.$x||t.x||{},this[S]=!0}var w=p.prototype;return w.parse=function(t){this.$d=function(t){var e=t.date,r=t.utc;if(null===e)return new Date(NaN);if(M.u(e))return new Date;if(e instanceof Date)return new Date(e);if("string"==typeof e&&!/Z$/i.test(e)){var n=e.match(d);if(n){var a=n[2]-1||0,s=(n[7]||"0").substring(0,3);return r?new Date(Date.UTC(n[1],a,n[3]||1,n[4]||0,n[5]||0,n[6]||0,s)):new Date(n[1],a,n[3]||1,n[4]||0,n[5]||0,n[6]||0,s)}}return new Date(e)}(t),this.init()},w.init=function(){var t=this.$d;this.$y=t.getFullYear(),this.$M=t.getMonth(),this.$D=t.getDate(),this.$W=t.getDay(),this.$H=t.getHours(),this.$m=t.getMinutes(),this.$s=t.getSeconds(),this.$ms=t.getMilliseconds()},w.$utils=function(){return M},w.isValid=function(){return!(this.$d.toString()===g)},w.isSame=function(t,e){var r=D(t);return this.startOf(e)<=r&&r<=this.endOf(e)},w.isAfter=function(t,e){return D(t)<this.startOf(e)},w.isBefore=function(t,e){return this.endOf(e)<D(t)},w.$g=function(t,e,r){return M.u(t)?this[e]:this.set(r,t)},w.unix=function(){return Math.floor(this.valueOf()/1e3)},w.valueOf=function(){return this.$d.getTime()},w.startOf=function(t,e){var r=this,n=!!M.u(e)||e,c=M.p(t),g=function(t,e){var a=M.w(r.$u?Date.UTC(r.$y,e,t):new Date(r.$y,e,t),r);return n?a:a.endOf(o)},d=function(t,e){return M.w(r.toDate()[t].apply(r.toDate("s"),(n?[0,0,0,0]:[23,59,59,999]).slice(e)),r)},m=this.$W,p=this.$M,w=this.$D,y="set"+(this.$u?"UTC":"");switch(c){case h:return n?g(1,0):g(31,11);case u:return n?g(1,p):g(0,p+1);case l:var $=this.$locale().weekStart||0,b=(m<$?m+7:m)-$;return g(n?w-b:w+(6-b),p);case o:case f:return d(y+"Hours",0);case i:return d(y+"Minutes",1);case s:return d(y+"Seconds",2);case a:return d(y+"Milliseconds",3);default:return this.clone()}},w.endOf=function(t){return this.startOf(t,!1)},w.$set=function(t,e){var r,l=M.p(t),c="set"+(this.$u?"UTC":""),g=(r={},r[o]=c+"Date",r[f]=c+"Date",r[u]=c+"Month",r[h]=c+"FullYear",r[i]=c+"Hours",r[s]=c+"Minutes",r[a]=c+"Seconds",r[n]=c+"Milliseconds",r)[l],d=l===o?this.$D+(e-this.$W):e;if(l===u||l===h){var m=this.clone().set(f,1);m.$d[g](d),m.init(),this.$d=m.set(f,Math.min(this.$D,m.daysInMonth())).$d}else g&&this.$d[g](d);return this.init(),this},w.set=function(t,e){return this.clone().$set(t,e)},w.get=function(t){return this[M.p(t)]()},w.add=function(n,c){var f,g=this;n=Number(n);var d=M.p(c),m=function(t){var e=D(g);return M.w(e.date(e.date()+Math.round(t*n)),g)};if(d===u)return this.set(u,this.$M+n);if(d===h)return this.set(h,this.$y+n);if(d===o)return m(1);if(d===l)return m(7);var p=(f={},f[s]=e,f[i]=r,f[a]=t,f)[d]||1,w=this.$d.getTime()+n*p;return M.w(w,this)},w.subtract=function(t,e){return this.add(-1*t,e)},w.format=function(t){var e=this,r=this.$locale();if(!this.isValid())return r.invalidDate||g;var n=t||"YYYY-MM-DDTHH:mm:ssZ",a=M.z(this),s=this.$H,i=this.$m,o=this.$M,l=r.weekdays,u=r.months,c=r.meridiem,h=function(t,r,a,s){return t&&(t[r]||t(e,n))||a[r].slice(0,s)},f=function(t){return M.s(s%12||12,t,"0")},d=c||function(t,e,r){var n=t<12?"AM":"PM";return r?n.toLowerCase():n};return n.replace(m,function(t,n){return n||function(t){switch(t){case"YY":return String(e.$y).slice(-2);case"YYYY":return M.s(e.$y,4,"0");case"M":return o+1;case"MM":return M.s(o+1,2,"0");case"MMM":return h(r.monthsShort,o,u,3);case"MMMM":return h(u,o);case"D":return e.$D;case"DD":return M.s(e.$D,2,"0");case"d":return String(e.$W);case"dd":return h(r.weekdaysMin,e.$W,l,2);case"ddd":return h(r.weekdaysShort,e.$W,l,3);case"dddd":return l[e.$W];case"H":return String(s);case"HH":return M.s(s,2,"0");case"h":return f(1);case"hh":return f(2);case"a":return d(s,i,!0);case"A":return d(s,i,!1);case"m":return String(i);case"mm":return M.s(i,2,"0");case"s":return String(e.$s);case"ss":return M.s(e.$s,2,"0");case"SSS":return M.s(e.$ms,3,"0");case"Z":return a}return null}(t)||a.replace(":","")})},w.utcOffset=function(){return 15*-Math.round(this.$d.getTimezoneOffset()/15)},w.diff=function(n,f,g){var d,m=this,p=M.p(f),w=D(n),y=(w.utcOffset()-this.utcOffset())*e,$=this-w,b=function(){return M.m(m,w)};switch(p){case h:d=b()/12;break;case u:d=b();break;case c:d=b()/3;break;case l:d=($-y)/6048e5;break;case o:d=($-y)/864e5;break;case i:d=$/r;break;case s:d=$/e;break;case a:d=$/t;break;default:d=$}return g?d:M.a(d)},w.daysInMonth=function(){return this.endOf(u).$D},w.$locale=function(){return b[this.$L]},w.locale=function(t,e){if(!t)return this.$L;var r=this.clone(),n=v(t,e,!0);return n&&(r.$L=n),r},w.clone=function(){return M.w(this.$d,this)},w.toDate=function(){return new Date(this.valueOf())},w.toJSON=function(){return this.isValid()?this.toISOString():null},w.toISOString=function(){return this.$d.toISOString()},w.toString=function(){return this.$d.toUTCString()},p}(),x=A.prototype;return D.prototype=x,[["$ms",n],["$s",a],["$m",s],["$H",i],["$W",o],["$M",u],["$y",h],["$D",f]].forEach(function(t){x[t[1]]=function(e){return this.$g(e,t[0],t[1])}}),D.extend=function(t,e){return t.$i||(t(e,A,D),t.$i=!0),D},D.locale=v,D.isDayjs=_,D.unix=function(t){return D(1e3*t)},D.en=b[$],D.Ls=b,D.p={},D}()}(zt);var Wt=qt(zt.exports),Bt={exports:{}};!function(t){var e,r,n;t.exports=(e="minute",r=/[+-]\d\d(?::?\d\d)?/g,n=/([+-]|\d\d)/g,function(t,a,s){var i=a.prototype;s.utc=function(t){return new a({date:t,utc:!0,args:arguments})},i.utc=function(t){var r=s(this.toDate(),{locale:this.$L,utc:!0});return t?r.add(this.utcOffset(),e):r},i.local=function(){return s(this.toDate(),{locale:this.$L,utc:!1})};var o=i.parse;i.parse=function(t){t.utc&&(this.$u=!0),this.$utils().u(t.$offset)||(this.$offset=t.$offset),o.call(this,t)};var l=i.init;i.init=function(){if(this.$u){var t=this.$d;this.$y=t.getUTCFullYear(),this.$M=t.getUTCMonth(),this.$D=t.getUTCDate(),this.$W=t.getUTCDay(),this.$H=t.getUTCHours(),this.$m=t.getUTCMinutes(),this.$s=t.getUTCSeconds(),this.$ms=t.getUTCMilliseconds()}else l.call(this)};var u=i.utcOffset;i.utcOffset=function(t,a){var s=this.$utils().u;if(s(t))return this.$u?0:s(this.$offset)?u.call(this):this.$offset;if("string"==typeof t&&(t=function(t){void 0===t&&(t="");var e=t.match(r);if(!e)return null;var a=(""+e[0]).match(n)||["-",0,0],s=a[0],i=60*+a[1]+ +a[2];return 0===i?0:"+"===s?i:-i}(t),null===t))return this;var i=Math.abs(t)<=16?60*t:t;if(0===i)return this.utc(a);var o=this.clone();if(a)return o.$offset=i,o.$u=!1,o;var l=this.$u?this.toDate().getTimezoneOffset():-1*this.utcOffset();return(o=this.local().add(i+l,e)).$offset=i,o.$x.$localOffset=l,o};var c=i.format;i.format=function(t){var e=t||(this.$u?"YYYY-MM-DDTHH:mm:ss[Z]":"");return c.call(this,e)},i.valueOf=function(){var t=this.$utils().u(this.$offset)?0:this.$offset+(this.$x.$localOffset||this.$d.getTimezoneOffset());return this.$d.valueOf()-6e4*t},i.isUTC=function(){return!!this.$u},i.toISOString=function(){return this.toDate().toISOString()},i.toString=function(){return this.toDate().toUTCString()};var h=i.toDate;i.toDate=function(t){return"s"===t&&this.$offset?s(this.format("YYYY-MM-DD HH:mm:ss:SSS")).toDate():h.call(this)};var f=i.diff;i.diff=function(t,e,r){if(t&&this.$u===t.$u)return f.call(this,t,e,r);var n=this.local(),a=s(t).local();return f.call(n,a,e,r)}})}(Bt);var Kt=qt(Bt.exports);Wt.extend(Kt);function Gt(t){let e=null;if(At(t)){if(0===t)return"";e=Wt.unix(t)}else if(t instanceof Date)e=Wt(t);else{if(!lt(t))return"";e=Wt(t)}return e.isValid()?e.utcOffset(8).format("YYYY-MM-DD HH:mm:ss"):""}let Xt={timeout:3e4,maxRetries:5,baseDelayMs:3e3,maxDelayMs:15e3,label:"fetch-ai-news-aggregator"};let Zt={nbsp:" ",amp:"&",lt:"<",gt:">",quot:'"',apos:"'",hellip:"…",mdash:"—",ndash:"–",middot:"·",ldquo:'"',rdquo:'"',lsquo:"‘",rsquo:"’",laquo:"«",raquo:"»",copy:"©",reg:"®"};function Jt(t){return ot(t)?t.replace(/&([a-zA-Z]+);/g,(t,e)=>void 0!==Zt[e]?Zt[e]:t).replace(/&#(\d+);/g,(t,e)=>String.fromCodePoint(Number(e))).replace(/&#x([\da-fA-F]+);/g,(t,e)=>String.fromCodePoint(parseInt(e,16))):""}function Vt(t,e={}){if(!ot(t))return"";let r=it(e,"image");dt(r)||(r=!1);let n=t;return n=n.replace(/<script[\s\S]*?<\/script>/gi,""),n=n.replace(/<style[\s\S]*?<\/style>/gi,""),n=n.replace(/<!--[\s\S]*?-->/g,""),r&&(n=n.replace(/<img[^>]*src="([^"]+)"[^>]*\/?>/gi,(t,e)=>`![](${e})`)),n=n.replace(/<h[1-6][^>]*>([\s\S]*?)<\/h[1-6]>/gi,"\n\n**$1**\n\n"),n=n.replace(/<\/?(?:strong|b)(?:\s[^>]*)?>/gi,"**"),n=n.replace(/<\/?(?:em|i)(?:\s[^>]*)?>/gi,"*"),n=n.replace(/<br\s*\/?>/gi,"\n"),n=n.replace(/<a\s+[^>]*href="([^"]+)"[^>]*>([\s\S]*?)<\/a>/gi,(t,e,r)=>{let n=r.replace(/<[^>]+>/g,"").trim();return n?`[${n}](${e})`:""}),n=n.replace(/<p(?:\s[^>]*)?>/gi,""),n=n.replace(/<\/p>/gi,"\n\n"),n=n.replace(/<\/?(?:div|span|section|article|font|u)(?:\s[^>]*)?>/gi,""),n=n.replace(/<[^>]+>/g,""),n=Jt(n),n=n.split("\n").map(t=>t.replace(/[ \t\u00A0]+/g," ").trimEnd()).join("\n"),n=n.replace(/\n{3,}/g,"\n\n").replace(/\*\*\s*\*\*/g,""),n.trim()}function Qt(t,e){if(!ot(t))return null;if(!lt(e))return null;let r=`<div class="${e}"`,n=t.indexOf(r);if(-1===n)return null;let a=t.indexOf(">",n);if(-1===a)return null;let s=a+1,i=s,o=1;for(;o>0&&i<t.length;){let e=t.indexOf("<div",i),r=t.indexOf("</div>",i);if(-1===r)return null;if(-1!==e&&e<r)o++,i=e+4;else{if(o--,0===o)return t.slice(s,r);i=r+6}}return null}function te(t){return ot(t)||(t=String(null==t?"":t)),t.replace(/[\\/:*?"<>|]/g,"_").slice(0,200)}let ee="https://www.aisixiang.com",re="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0 Safari/537.36",ne={responseType:"text",headers:{"User-Agent":re,"Accept-Language":"zh-CN,zh;q=0.9"},timeout:3e4,maxRetries:5,baseDelayMs:5e3,maxDelayMs:3e4,label:"fetch-aisixiang"};function ae(t={}){let e=it(t,"baseUrl");lt(e)||(e=ee),e=e.replace(/\/+$/,"");let r=Ht(t,ne),n=it(t,"pageDelayMs");n=Ct(n)?Lt(n):1e3;let a=it(t,"maxPages");return a=Pt(a)?Math.min(Lt(a),50):50,{baseUrl:e,showLog:r.showLog,pageDelayMs:n,maxPages:a,optFetch:r}}function se(t,e){let r=Qt(t,"search_list");if(null===r)return[];let n,a=[],s=new Set,i=/href="\/data\/(\d+)\.html"[^>]*title="([^"]+)"/g;for(;null!==(n=i.exec(r));){if(s.has(n[1]))continue;s.add(n[1]);let t=n[2],r=t.indexOf(":");a.push({aid:n[1],url:`${e}/data/${n[1]}.html`,title:r>0?t.slice(r+1).trim():t.trim(),author:r>0?t.slice(0,r).trim():""})}return a}function ie(t,e){let r,n=t.match(/([\s\S]+?)<div class="list_page">/),a=n?n[1]:t,s=[],i=new Set,o=/<a\s+href="\/data\/(\d+)\.html"[^>]*>([^<]+)<\/a>/g;for(;null!==(r=o.exec(a));){if(i.has(r[1]))continue;i.add(r[1]);let t=r[2].trim(),n=t.indexOf(":");s.push({aid:r[1],url:`${e}/data/${r[1]}.html`,title:n>0?t.slice(n+1).trim():t,author:n>0?t.slice(0,n).trim():""})}return s}function oe(t){let e=t.match(/<div class="list_page">([\s\S]+?)<\/div>/);if(!e)return 1;let r=[...e[1].matchAll(/page=(\d+)/g)].map(t=>Number(t[1]));return r.length?Math.max(...r):1}async function le(t,e,r){let n=[],a=new Set,s=1,i=0;for(let o=1;o<=r.maxPages;o++){let l=t(o);r.showLog&&process.stderr.write(`[info] fetching page ${o}${s>1?`/${s}`:""} ...\n`);let u=await Nt(l,r.optFetch);i++,1===o&&(s=oe(u));let c=e(u,r.baseUrl).filter(t=>!a.has(t.aid));if(0===c.length){r.showLog&&process.stderr.write(`[info] page ${o} 無新項目,停止翻頁\n`);break}for(let t of c)a.add(t.aid);if(n.push(...c),o>=s)break;await It(r.pageDelayMs)}return{items:n,total_pages:s,pages_fetched:i}}async function ue(t={}){let e=ae(t),r=[...(await Nt(`${e.baseUrl}/thinktank/`,e.optFetch)).matchAll(/href="\/thinktank\/([^"]+?)\.html"[^>]*>([^<]+)</g)],n=new Map;for(let[,t,e]of r){let r=t.toLowerCase();if(n.has(r))continue;let a=e.split(/[,、]/)[0].trim();!a||a.length>30||n.set(r,{slug:t,name:a})}return[...n.values()]}function ce(t,e){return Array.isArray(t)&&t.find(t=>t.name===e)||null}async function he(t={}){let e=ae(t),r=await Nt(`${e.baseUrl}/zhuanti/`,e.optFetch),n=[{name:"学科",start:r.indexOf("<h3>学科关键词</h3>")},{name:"事件",start:r.indexOf("<h3>事件关键词</h3>")},{name:"人物",start:r.indexOf("<h3>人物关键词</h3>")}].filter(t=>t.start>=0).sort((t,e)=>t.start-e.start);n.push({name:null,start:r.length});let a=new Set,s=[];for(let t=0;t<n.length-1;t++){let e,i=r.slice(n[t].start,n[t+1].start),o=/href="\/zhuanti\/(\d+)\.html"[^>]*>([^<]+)</g;for(;null!==(e=o.exec(i));){if(a.has(e[1]))continue;a.add(e[1]);let r=e[2].trim().replace(/^\[|\]$/g,"").trim();!r||r.length>50||s.push({id:e[1],name:r,category:n[t].name})}}return s}function fe(t,e){return Array.isArray(t)&&t.find(t=>t.name===e)||null}let ge={BASE_URL:ee,USER_AGENT:re,MAX_PAGES:50,safeFilename:te,fetchAuthorsList:ue,lookupAuthor:ce,fetchTopicsList:he,lookupTopic:fe,fetchAuthorArticles:async function(t={}){let e=ae(t),r=it(t,"name");lt(r)||(r="");let n=it(t,"slug");if(lt(n)||(n=""),!r&&!n)throw new Error("需要 name 或 slug");let a=null,s=r,i=n;if(i)a={slug:i,url:`${e.baseUrl}/thinktank/${i}.html`};else{e.showLog&&process.stderr.write("[info] fetching authors list from /thinktank/ ...\n");let n=await ue(t),o=ce(n,r);if(!o)return{status:"success",site:"aisixiang",mode:"author",query:r,fetched_at:(new Date).toISOString(),authors_count:n.length,count:0,items:[],message:`"${r}" 不在愛思想專欄作者清單中(共 ${n.length} 位)。尚無此作者文章(此為查詢成功的真實結果、0 筆,非抓取失敗)。提醒:本函數不轉簡繁,呼叫端負責用站方登錄字形(通常是簡體)。`};i=o.slug,s=s||o.name,a={slug:i,url:`${e.baseUrl}/thinktank/${i}.html`,name:o.name}}let o=function(t,e){let r=["论文","时评","随笔","著作","演讲","读书","访谈","未分类"],n=[];for(let e of r){let r,a=new RegExp(`<h3>${e}<\\/h3>`,"g");for(;null!==(r=a.exec(t));)n.push({cat:e,pos:r.index})}n.sort((t,e)=>t.pos-e.pos),n.push({cat:null,pos:t.length});let a=[];for(let r=0;r<n.length-1;r++){let s,{cat:i,pos:o}=n[r],l=t.slice(o,n[r+1].pos),u=/<a\s+href="\/data\/(\d+)\.html"[^>]*>([\s\S]*?)<\/a>/g;for(;null!==(s=u.exec(l));){let t=s[2].replace(/<[^>]+>/g,"").trim();t&&a.push({aid:s[1],url:`${e}/data/${s[1]}.html`,title:t,category:i})}}return a}(await Nt(a.url,e.optFetch),e.baseUrl),l={status:"success",site:"aisixiang",mode:"author",query:s||i,resolved:a,fetched_at:(new Date).toISOString(),count:o.length,items:o};return 0===o.length&&(l.message=`已命中愛思想作者欄頁(${a.url})但該欄頁目前 0 篇文章。此為查詢成功的真實結果(非抓取失敗);若 slug 為手動指定,請確認 slug 是否正確。`),l},fetchKeywordArticles:async function(t,e={}){if(!lt(t))throw new Error("需要 keyword");let r=ae(e),n=e=>`${r.baseUrl}/data/search?searchfield=keywords&keywords=${encodeURIComponent(t)}&page=${e}`,{items:a,total_pages:s,pages_fetched:i}=await le(n,se,r);return 0===a.length?{status:"success",site:"aisixiang",mode:"keyword",query:t,resolved:{search_url:n(1)},fetched_at:(new Date).toISOString(),count:0,items:[],message:`關鍵字 "${t}" 在愛思想無相關文章。提醒:站方搜尋只認簡體,呼叫端負責簡體化;若已是簡體仍 0 筆,該主題可能無 tag 索引。`}:{status:"success",site:"aisixiang",mode:"keyword",query:t,resolved:{search_url:n(1),total_pages:s,pages_fetched:i},fetched_at:(new Date).toISOString(),count:a.length,items:a}},fetchTitleArticles:async function(t,e={}){if(!lt(t))throw new Error("需要 keyword");let r=ae(e),n=e=>`${r.baseUrl}/data/search?searchfield=title&keywords=${encodeURIComponent(t)}&page=${e}`,{items:a,total_pages:s,pages_fetched:i}=await le(n,se,r);return 0===a.length?{status:"success",site:"aisixiang",mode:"title",query:t,resolved:{search_url:n(1)},fetched_at:(new Date).toISOString(),count:0,items:[],message:`標題關鍵字 "${t}" 在愛思想無相關文章。提醒:站方搜尋只認簡體,呼叫端負責簡體化。`}:{status:"success",site:"aisixiang",mode:"title",query:t,resolved:{search_url:n(1),total_pages:s,pages_fetched:i},fetched_at:(new Date).toISOString(),count:a.length,items:a}},fetchTopicArticles:async function(t={}){let e=ae(t),r=it(t,"keyword");lt(r)||(r="");let n=it(t,"id");if(lt(n)||(n=""),!r&&!n)throw new Error("需要 keyword 或 id");let a=n,s=r,i=null;if(a)i={id:a,url:`${e.baseUrl}/zhuanti/${a}.html`};else{e.showLog&&process.stderr.write("[info] fetching topics list from /zhuanti/ ...\n");let n=await he(t),o=fe(n,r);if(!o)return{status:"success",site:"aisixiang",mode:"topic",query:r,fetched_at:(new Date).toISOString(),topics_count:n.length,count:0,items:[],message:`"${r}" 不在愛思想策展主題清單中(共 ${n.length} 個主題)。建議改用 fetchKeywordArticles('${r}') 查 keyword tag 結果。本函數不自動轉向,請呼叫端決定是否重試。`};a=o.id,s=o.name,i={id:a,name:o.name,category:o.category,url:`${e.baseUrl}/zhuanti/${a}.html`}}let{items:o,total_pages:l,pages_fetched:u}=await le(t=>`${e.baseUrl}/zhuanti/${a}.html?page=${t}`,ie,e),c={status:"success",site:"aisixiang",mode:"topic",query:s||a,resolved:{...i,total_pages:l,pages_fetched:u},fetched_at:(new Date).toISOString(),count:o.length,items:o};return 0===o.length&&(c.message=`已命中愛思想策展主題(${i.url})但該主題頁目前 0 篇文章。此為查詢成功的真實結果(非抓取失敗);若需更多結果可改用 fetchKeywordArticles 查 keyword tag。`),c},fetchArticle:async function(t={}){let e=ae(t),r=it(t,"aid");lt(r)||(r="");let n=it(t,"url");lt(n)||(n="");let a=r?`${e.baseUrl}/data/${r}.html`:n;if(!a)throw new Error("需要 aid 或 url");let s=await Nt(a,e.optFetch),i=function(t){let e=t.match(/<title>([\s\S]*?)<\/title>/i);return e?Jt(e[1].trim()):null}(s),o=Qt(s,"article-content");if(!i||!o)throw new Error(`解析失敗:title=${!!i}, content=${!!o}`);let l=Vt(o),u=i.replace(/[_\-\s]*(?:_)?(?:爱思想|愛思想)\s*$/u,"").trim(),c=`---\ntitle: "${u}"\nsource: "${a}"\nauthor:\npublished:\ncreated: ${(new Date).toISOString().slice(0,10)}\ndescription:\n---\n${l}\n`;return{status:"success",site:"aisixiang",mode:"fetch",url:a,title:u,chars:l.length,markdown:c}}},de={timeout:3e4,maxRetries:10,baseDelayMs:5e3,maxDelayMs:3e4,retryStatus:[403],label:"fetch-cnyes"};let{fetchWebByCurl:me}=t,pe="https://www.guancha.cn",we="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",ye=[{slug:"CaiJing",name:"财经"},{slug:"economy",name:"财经-大頻道"},{slug:"JunShi",name:"军事"},{slug:"military-affairs",name:"军事-大頻道"},{slug:"ZhengZhi",name:"政治"},{slug:"WenHua",name:"文化"},{slug:"chanjing",name:"产经"},{slug:"qiche",name:"观出行"},{slug:"gongye-keji",name:"科技"},{slug:"ChengShi",name:"城事"},{slug:"GuanJinRong",name:"观金融"},{slug:"XinShiDai",name:"新时代"},{slug:"ChaoJiGongCheng",name:"超级工程"},{slug:"NengYuanZhanLue",name:"能源战略"},{slug:"RenGongZhiNeng",name:"人工智能"},{slug:"XinZhiGuanChaSuoNews",name:"心智观察所"},{slug:"YiLangJuShi",name:"伊朗局势"},{slug:"MeiGuoMeng",name:"美国一梦"},{slug:"MeiGuoJingJi",name:"美国经济"},{slug:"ELuoSiZhiSheng",name:"俄罗斯之声"},{slug:"lianganyuanzhuopai",name:"两岸圆桌派"},{slug:"ZheJiuShiZhongGuo",name:"这就是中国"},{slug:"YiZhouJunQingGuanCha",name:"一周军事观察"},{slug:"feizhoushangkou",name:"非洲之窗"},{slug:"toutiao",name:"观察者头条"},{slug:"gushi",name:"股市"},{slug:"guanwangwenyu",name:"新潮观鱼"},{slug:"jingtiriben",name:"冲破战后秩序 日本想干什么"},{slug:"DaoGuoDianAVI",name:"日本"}];function $e(t={}){let e=it(t,"baseUrl");lt(e)||(e=pe),e=e.replace(/\/+$/,"");let r=it(t,"maxRetries");r=Ct(r)?Lt(r):5;let n=it(t,"timeout");n=Pt(n)?Lt(n):null;let a=it(t,"showLog");dt(a)||(a=!0);let s={userAgent:we,referer:e,maxRetries:r};null!==n&&(s.timeoutMs=n);let i=it(t,"pageDelayMs");i=Ct(i)?Lt(i):1e3;let o=it(t,"maxPages");return o=Pt(o)?Math.min(Lt(o),50):50,{baseUrl:e,showLog:a,pageDelayMs:i,maxPages:o,optFetch:s}}async function be(t,e){let r=await me(t,e.optFetch);if("success"!==r.status){let e=new Error(r.message||"fetch failed");throw e.reason=r.reason,e.url=t,e.httpCode=r.httpCode,e}return r.html}function Se(t){let e=t.match(/<dt>[A-Z]<\/dt>/g);return!!e&&e.length>=5}function _e(t,e){let r,n=t.replace(/\n/g," "),a=[],s=new Set,i=/<a[^>]+href="\/([A-Za-z][a-zA-Z0-9_-]+)\/(\d{4}_\d{2}_\d{2}_\d+)\.shtml"(?:[^>]*title="([^"]+)")?[^>]*>([^<]*)<\/a>/g;for(;null!==(r=i.exec(n));){let t=r[1],n=r[2],i=r[3]&&Jt(r[3]).trim(),o=r[4]&&Jt(r[4]).replace(/<[^>]+>/g,"").trim(),l=i||o||"",u=`${t}/${n}`;!s.has(u)&&l&&(s.add(u),a.push({url:`${e}/${t}/${n}.shtml`,title:l,slug:t}))}return a}async function ve(t,e){let r=[],n=new Set,a=0;for(let s=1;s<=e.maxPages;s++){let i=`${e.baseUrl}/${t}/list_${s}.shtml`;e.showLog&&process.stderr.write(`[info] fetching ${t} list_${s} ...\n`);let o=null;try{o=await be(i,e)}catch(t){if(1===s)throw t;e.showLog&&process.stderr.write(`[info] page ${s} fetch error (assumed end of list): ${t.message}\n`);break}if(Se(o)){if(1===s){let e=new Error(`slug "${t}" 不存在:請求 list 頁被觀察者網 302 導向首頁。`);throw e.reason="redirected-to-homepage",e}e.showLog&&process.stderr.write(`[info] page ${s} 被導向首頁,視為到底,停止翻頁\n`);break}a++;let l=_e(o,e.baseUrl).filter(t=>!n.has(t.url));if(0===l.length){e.showLog&&process.stderr.write(`[info] page ${s} 無新項目,停止翻頁\n`);break}for(let t of l)n.add(t.url);r.push(...l),s<e.maxPages&&await It(e.pageDelayMs)}return{items:r,pages_fetched:a}}async function De(t={}){let e=$e(t);return function(t){let e=t.replace(/\n/g," "),r=[],n=new Set,a=[...e.matchAll(/<dt>([A-Z])<\/dt>\s*<dd[^>]*>([\s\S]*?)<\/dd>/g)];for(let[,t,e]of a){let a,s=/<a[^>]+href="(?:\.\.\/|\/)?([A-Za-z][a-zA-Z0-9_-]+)\/list_1\.shtml"[^>]*>([^<]+)<\/a>/g;for(;null!==(a=s.exec(e));){let e=a[1],s=Jt(a[2]).trim();s&&!n.has(e)&&(n.add(e),r.push({slug:e,name:s,letter:t}))}}return r}(await be(`${e.baseUrl}/`,e))}function Me(t,e){return Array.isArray(t)&&e&&t.find(t=>t.name===e)||null}function Ae(t){return t&&ye.find(e=>e.name===t)||null}let xe={timeout:3e4,maxRetries:5,baseDelayMs:3e3,maxDelayMs:15e3,label:"fetch-hacker-news"};let Te={responseType:"text",timeout:3e4,maxRetries:10,baseDelayMs:5e3,maxDelayMs:3e4,retryStatus:[403],label:"fetch-moneydj"},Ee=/^(\d{2}\/\d{2}\s+\d{2}:\d{2}|\d{2}:\d{2}|昨\s*\d{2}:\d{2})$/;let Oe=5e3,ke=3e4,je=[{name:"上市",marketKind:"sii"},{name:"上櫃",marketKind:"otc"},{name:"興櫃",marketKind:"rotc"},{name:"公開發行",marketKind:"pub"}];async function Le(t,e,r){let n=null;for(let a=1;a<=r.maxRetries+1;a++){if(n=await t.evaluate(async t=>{try{let e=await fetch(t.url,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t.payload)});if(e.status>=500||403===e.status||429===e.status)return{error:`HTTP ${e.status}`,retryable:!0};let r=await e.text();try{let t=JSON.parse(r),e=t&&t.code;return 200!==e&&406!==e?{error:`MOPS code ${e}: ${t&&t.message||""}`,json:t,raw:r.substring(0,500),retryable:!1}:{json:t,raw:r.substring(0,500)}}catch(t){return{error:"Parse Error",raw:r,retryable:!1}}}catch(t){return{error:t.toString(),retryable:!0}}},e),!n.error)return n;let s=!1!==n.retryable,i=r.maxRetries+1-a;if(!s||i<=0)return n;let o=Math.min(r.baseDelayMs*a,r.maxDelayMs);r.showLog&&console.warn(`[${e.name}][Retry ${a}/${r.maxRetries}] ${n.error} — 等待 ${o/1e3}s 後重試...`),await It(o)}return n}let Pe={responseType:"text",timeout:3e4,maxRetries:5,baseDelayMs:3e3,maxDelayMs:15e3,retryStatus:[404],label:"fetch-rss"};let Ce={responseType:"text",timeout:3e4,maxRetries:10,baseDelayMs:5e3,maxDelayMs:3e4,retryStatus:[403],label:"fetch-statementdog"},Ie=".statementdog-news-list-item";function Ue(t){if(!lt(t))return!1;if(!/^\d{8}$/.test(t))return!1;let e=Lt(t.slice(0,4)),r=Lt(t.slice(4,6)),n=Lt(t.slice(6,8)),a=new Date(e,r-1,n);return a.getFullYear()===e&&a.getMonth()===r-1&&a.getDate()===n}let Re={responseType:"text",encoding:"big5",timeout:15e3,maxRetries:10,baseDelayMs:5e3,maxDelayMs:3e4,label:"fetch-taifex"},Ye={"外資及陸資":"foreign","外資":"foreign","投信":"trust","自營商":"dealers"};function Ne(t){let e=[],r="",n=!1;for(let a=0;a<t.length;a++){let s=t[a];n?'"'===s?'"'===t[a+1]?(r+='"',a++):n=!1:r+=s:","===s?(e.push(r.trim()),r=""):'"'===s&&0===r.length?n=!0:r+=s}return e.push(r.trim()),e}function Fe(t){let e=t.trim().split("\n").map(t=>t.trim()).filter(t=>t.length>0);if(e.length<2)return[];let r=Ne(e[0]),n=[];for(let t=1;t<e.length;t++){let a=Ne(e[t]),s={};for(let t=0;t<r.length;t++)s[r[t]]=a[t]||"";n.push(s)}return n}function He(t){if(!t||"-"===t||""===t)return null;let e=Number(t.replace(/,/g,""));return isNaN(e)?null:e}function qe(t){if(!lt(t))return"";return`${parseInt(t.substring(0,4),10)-1911}/${t.substring(4,6)}/${t.substring(6,8)}`}let ze={timeout:15e3,maxRetries:10,baseDelayMs:5e3,maxDelayMs:3e4,label:"fetch-tpex-3insti"},We=["代號","名稱","外陸資買進股數(不含外資自營商)","外陸資賣出股數(不含外資自營商)","外陸資買賣超股數(不含外資自營商)","外資自營商買進股數","外資自營商賣出股數","外資自營商買賣超股數","外資及陸資買進股數","外資及陸資賣出股數","外資及陸資買賣超股數","投信買進股數","投信賣出股數","投信買賣超股數","自營商買進股數(自行買賣)","自營商賣出股數(自行買賣)","自營商買賣超股數(自行買賣)","自營商買進股數(避險)","自營商賣出股數(避險)","自營商買賣超股數(避險)","自營商買進股數","自營商賣出股數","自營商買賣超股數","三大法人買賣超股數合計"];function Be(t){return"string"!=typeof t?t:parseInt(t.replace(/,/g,""),10)||0}let Ke={timeout:15e3,maxRetries:10,baseDelayMs:5e3,maxDelayMs:3e4,label:"fetch-tpex-margin"};let Ge={timeout:15e3,maxRetries:10,baseDelayMs:5e3,maxDelayMs:3e4,label:"fetch-tpex-stock"};let Xe={responseType:"text",timeout:3e4,maxRetries:10,baseDelayMs:5e3,maxDelayMs:3e4,label:"fetch-tw-data-holiday"};let Ze={timeout:15e3,maxRetries:10,baseDelayMs:5e3,maxDelayMs:3e4,label:"fetch-twse-margin"};let Je={timeout:1e4,maxRetries:10,baseDelayMs:5e3,maxDelayMs:3e4,label:"fetch-twse-stock"};let Ve={timeout:15e3,maxRetries:10,baseDelayMs:5e3,maxDelayMs:3e4,label:"fetch-twse-t86"};let Qe={fetchRSS:async function(t,e={}){if(!lt(t)||!/^https?:\/\//i.test(t))throw new Error("rssUrl 須為有效的 http/https RSS 網址");let r=await Nt(t,Ht(e,Pe)),a=new n,s=await a.parseString(r),i=String(it(s,"title","")||"").trim(),o=it(s,"items");return gt(o)||(o=[]),o.map(t=>({url:String(it(t,"link","")||"").trim(),time:Gt(it(t,"isoDate","")||it(t,"pubDate","")),title:String(it(t,"title","")||"").trim(),description:String(it(t,"contentSnippet","")||it(t,"summary","")||"").trim(),from:String(it(t,"creator","")||i).trim()}))},fetchHackerNews:async function(t=30,e={}){t=Pt(t)?Lt(t):30;let r=it(e,"apiBase");lt(r)||(r="https://hacker-news.firebaseio.com/v0"),r=r.replace(/\/+$/,"");let n=Ht(e,xe),a=await Nt(`${r}/newstories.json`,n);gt(a)||(a=[]);let s=a.slice(0,t),i=[];for(let t=0;t<s.length;t+=10){let e=s.slice(t,t+10),a=await Promise.allSettled(e.map(t=>Nt(`${r}/item/${t}.json`,n)));for(let t of a)"fulfilled"===t.status&&i.push(t.value)}return i.filter(t=>t&&"story"===t.type).map(t=>({url:String(it(t,"url","")||`https://news.ycombinator.com/item?id=${it(t,"id","")}`).trim(),time:Gt(it(t,"time",0)),title:String(it(t,"title","")||"").trim(),description:"",from:"Hacker News"}))},fetchAiNewsAggregator:async function(t={}){let e=it(t,"url");lt(e)||(e="https://raw.githubusercontent.com/SuYxh/ai-news-aggregator/refs/heads/main/data/latest-24h.json");let r=it(await Nt(e,Ht(t,Xt)),"items");return gt(r)||(r=[]),r.map(t=>({url:String(it(t,"url","")||"").trim(),time:Gt(it(t,"published_at","")),title:String(it(t,"title","")||"").trim(),description:"",from:String(it(t,"source","")||"").trim()}))},fetchCnyes:async function(t={}){let e=it(t,"url");lt(e)||(e="https://api.cnyes.com/media/api/v1/newslist/category/tw_stock");let r=it(t,"targetTotal");r=Pt(r)?Lt(r):100;let n=it(t,"pageLimit");n=Pt(n)?Lt(n):30;let a=it(t,"daysBack");a=Pt(a)?Lt(a):10;let s=it(t,"pageDelayMs");s=Ct(s)?Lt(s):500;let i=Ht(t,de),o=i.showLog,l=Math.floor(Date.now()/1e3),u=l-86400*a;o&&console.log("Starting to fetch Anue (tw_stock) news...");let c=[],h=1;for(;c.length<r;){let t=new URLSearchParams({page:String(h),limit:String(n),isCategoryHeadline:"1",startAt:String(u),endAt:String(l)}),r=it(await Nt(`${e}?${t.toString()}`,i),"items.data");if(!gt(r)){o&&console.log("No more items found.");break}c=c.concat(r),o&&console.log(`Page ${h}: Fetched ${r.length} items. Total so far: ${c.length}`),h++,await It(s)}let f=c.slice(0,r);return o&&console.log(`Total items collected: ${f.length}`),f.map(t=>{let e=Gt(it(t,"publishAt",0));return""===e&&o&&console.warn(`[fetch-cnyes] 時間格式化失敗(newsId=${it(t,"newsId","")}, publishAt=${it(t,"publishAt","")}) — 該筆time退回空字串`),{time:e,title:it(t,"title",""),link:`https://news.cnyes.com/news/id/${it(t,"newsId","")}`}})},fetchMoneydj:async function(t={}){let e=it(t,"baseUrl");lt(e)||(e="https://www.moneydj.com/kmdj/news/newsreallist.aspx?a=mb06&index1=");let r=it(t,"totalPages");r=Pt(r)?Lt(r):50;let n=it(t,"onPageDone");(function(t){let e=Object.prototype.toString.call(t);return"[object Function]"===e||"[object AsyncFunction]"===e})(n)||(n=()=>{});let a=Ht(t,Te),i=a.showLog,o=it(t,"pageDelayMs");o=Pt(o)||0===o?Lt(o):null;let l=new URL(e).origin,u=async t=>{let r=await Nt(`${e}${t}`,{...a,label:`${Te.label} Page ${t}`}),n=s.load(r),i=[];return n("tr").each((t,e)=>{let r=n(e),a=r.find("td").eq(0).text().trim(),s=r.find("td").eq(1).find("a");if(a&&Ee.test(a)&&s.length>0){let t=s.attr("title")||s.text().trim(),e=s.attr("href");if(e){let r=e.startsWith("http")?e:l+e;i.push({time:a,title:t,link:r})}}}),i},c=[];for(let t=1;t<=r;t++){let e=null;try{e=await u(t)}catch(e){i&&console.warn(`[Page ${t}] 抓取失敗,已跳過:${e.message}`);continue}c=c.concat(e),n(t,e.length,r),t<r&&await It(null===o?Math.floor(2e3*Math.random())+1e3:o)}if(0===c.length)throw new Error("抓取到 0 筆新聞,可能是頁面結構改變或 selector 失效,請確認 MoneyDJ 頁面是否正常。");return c},fetchStatementdog:async function(t={}){let e=it(t,"url");lt(e)||(e="https://statementdog.com/news/latest");let r=Ht(t,Ce),n=r.showLog;n&&console.log(`Fetching ${e}...`);let a=await Nt(e,r),i=new URL(e).origin,o=s.load(a),l=o(Ie).length>0,u=l?Ie:'article, .news-item, [class*="news"][class*="item"]',c=l?".statementdog-news-list-item-title":'h2, h3, [class*="title"]',h=l?".statementdog-news-list-item-link":"a[href]",f=l?".statementdog-news-list-item-date":'time, [class*="date"], [class*="time"]';!l&&n&&console.warn("主要 CSS selector 未匹配,嘗試 fallback selector...");let g=[];if(o(u).each((t,e)=>{let r=o(e).find(c),n=l?o(e).find(h):o(e).find(h).first(),a=o(e).find(f),s=r.text().trim(),u=n.attr("href"),d=a.text().trim();s&&u&&(u.startsWith("http")||(u=`${i}${u.startsWith("/")?"":"/"}${u}`),g.push({time:d,title:s,link:u}))}),n&&console.log(`Extracted News Items: ${g.length}`),0===g.length)throw new Error("抓取到 0 筆新聞,可能是頁面結構改變或 selector 失效,請確認財報狗頁面是否正常。");return g},fetchMops:async function(t={}){let e=it(t,"pageUrl");lt(e)||(e="https://mops.twse.com.tw/mops/#/web/t146sb10");let n=it(t,"apiUrl");lt(n)||(n="https://mops.twse.com.tw/mops/api/t146sb10");let a=it(t,"maxRetries");a=Ct(a)?Lt(a):10;let s=it(t,"showLog");dt(s)||(s=!0);let i={maxRetries:a,baseDelayMs:Oe,maxDelayMs:ke,showLog:s},o=je.map(t=>{return{name:t.name,marketKind:t.marketKind,url:n,payload:(e=t.marketKind,{scopeType:"2",companyId:"",dateType:"2",firstDate:"",lastDate:"",marketKind:e,announcementBasis:"0",dateRangeType:"1",announcementType:"1",sort:"1",encodeURIComponent:1,step:1,firstin:1,off:1})};var e});s&&console.log("啟動瀏覽器...");let l=null;for(let t=1;t<=a+1;t++)try{l=await r.chromium.launch({headless:!0,executablePath:process.env.CHROME_PATH||void 0,channel:"chrome",args:["--no-sandbox","--disable-setuid-sandbox"],timeout:36e4});break}catch(e){if(a+1-t<=0)throw new Error(`瀏覽器啟動失敗(已重試 ${a} 次): ${e.message}`);let r=Math.min(Oe*t,ke);s&&console.warn(`[browser.launch][Retry ${t}/${a}] ${e.message} — 等待 ${r/1e3}s 後重試...`),await It(r)}try{let t=await l.newPage();s&&console.log("前往 MOPS 重大訊息頁面 (t146sb10)...");for(let r=1;r<=a+1;r++)try{await t.goto(e,{waitUntil:"networkidle",timeout:6e4});break}catch(t){if(a+1-r<=0)throw t;let e=Math.min(Oe*r,ke);s&&console.warn(`[page.goto][Retry ${r}/${a}] ${t.message} — 等待 ${e/1e3}s 後重試...`),await It(e)}await t.waitForTimeout(2e3);let r=[];for(let e of o){s&&console.log(`正在抓取 [${e.name}] 資料...`);let n=await Le(t,e,i);r.push({market:e.name,marketKind:e.marketKind,data:n.json||n,...n.error&&{error:n.error},timestamp:(new Date).toISOString()}),await t.waitForTimeout(1e3)}if(s){let t=r.map(t=>{let e=it(t,"data.result",it(t,"data")),r=Array.isArray(e)?e.length:0;return`${t.market}: 取得 ${r} 筆資料`});console.log("抓取完成。摘要:",t)}let n=r.some(t=>t.error);return{results:r,hasError:n}}finally{await l.close()}},fetchTwseStock:async function(t,e,r={}){if(!Ue(t))throw new Error(`dateStr 須為合法之 YYYYMMDD 字串,得到: ${t}`);let n=it(r,"baseUrl");lt(n)||(n="https://www.twse.com.tw"),n=n.replace(/\/+$/,"");let a=Ht(r,Je),s=a.showLog,i=lt(e)&&"all"!==e.toLowerCase(),o=i?e:"ALLBUT0999",l="";l=i?`${n}/exchangeReport/STOCK_DAY?response=json&date=${t}&stockNo=${o}`:`${n}/exchangeReport/MI_INDEX?response=json&date=${t}&type=ALLBUT0999`,s&&(console.log(`Fetching TWSE data: ${t}, Stock: ${o}`),console.log(`URL: ${l}`));let u=await Nt(l,a);if("OK"!==it(u,"stat"))throw new Error(`TWSE API returned: ${it(u,"stat")}`);if(i&&Array.isArray(u.data)){let r=qe(t),n=u.data.filter(t=>t[0]===r);if(u.data=n,0===n.length)throw new Error(`TWSE 個股 ${e} 於 ${t} 無交易資料(可能為假日或停盤)`)}return u},fetchTpexStock:async function(t,e,r={}){if(!Ue(t))throw new Error(`dateStr 須為合法之 YYYYMMDD 字串,得到: ${t}`);let n=it(r,"baseUrl");lt(n)||(n="https://www.tpex.org.tw"),n=n.replace(/\/+$/,"");let a=Ht(r,Ge),s=a.showLog,i=gt(e)?e:[],o=qe(t),l=`${n}/web/stock/aftertrading/daily_close_quotes/stk_quote_result.php?l=zh-tw&d=${o}&s=0,asc,0&o=json`;s&&(console.log(`Fetching TPEX data: ${t} (${o})`),console.log(`Target: ${i.length>0?i.join(", "):"All Market"}`),console.log(`URL: ${l}`));let u=await Nt(l,a),c=Array.isArray(u.tables)?u.tables:[],h=c.find(t=>it(t,"title","").includes("行情")&&it(t,"data.length",0)>0)||c.find(t=>it(t,"data.length",0)>0),f=it(h,"data");if(!gt(f))throw new Error("TPEX API returned no data. Possibly a holiday or data not yet available.");if(!Array.isArray(f[0])||f[0].length<8)throw new Error(`TPEX 行情資料欄數不符預期(首列 ${Array.isArray(f[0])?f[0].length:"N/A"} 欄,應 >= 8),可能 API 格式變更`);let g=f;if(i.length>0&&(g=g.filter(t=>i.includes(t[0])),0===g.length))throw new Error(`指定個股 ${i.join(",")} 在 ${t} 之上櫃資料中查無資料(可能為上市股、代碼有誤、或當日無交易)`);return{source:"tpex",date:t,count:g.length,data:g}},fetchTwseMargin:async function(t,e,r={}){if(!lt(t)||!/^\d{8}$/.test(t))throw new Error(`日期參數無效:格式須為 YYYYMMDD (收到 "${t}")`);if(!Ue(t))throw new Error(`日期參數無效:不合法的日期 (${t})`);let n=it(r,"baseUrl");lt(n)||(n="https://www.twse.com.tw"),n=n.replace(/\/+$/,"");let a=Ht(r,Ze),s=a.showLog,i=gt(e)?e.filter(Boolean):[],o=`${n}/rwd/zh/marginTrading/MI_MARGN?date=${t}&selectType=ALL&response=json`;s&&(console.log(`Fetching TWSE margin data: ${t}`),console.log(`Target: ${i.length>0?i.join(", "):"All Market"}`),console.log(`URL: ${o}`));let l=await Nt(o,a);if("OK"!==it(l,"stat"))throw new Error(`TWSE MI_MARGN API returned: ${it(l,"stat")}`);let u=Array.isArray(l.tables)?l.tables:[],c=u.find(t=>it(t,"data.length",0)>0&&it(t,"title","").includes("融資融券彙總"));if(c||(c=u.find(t=>it(t,"data.length",0)>0&&Array.isArray(t.fields)&&t.fields.some(t=>String(t).includes("融資"))&&t.fields.some(t=>String(t).includes("融券")))),!c||!gt(it(c,"data")))throw new Error("TWSE MI_MARGN: 找不到融資融券彙總資料表");if(!Array.isArray(c.fields)||c.fields.length<16)throw new Error(`TWSE 融資融券資料欄數不符預期(fields ${it(c,"fields.length","N/A")} 欄,應 >= 16),可能 API 格式變更`);let h=c.data;if(i.length>0&&(h=h.filter(t=>i.includes(String(t[0]||"").trim())),0===h.length))throw new Error(`指定個股 ${i.join(",")} 不在上市融資融券資料中(可能為上櫃股或代碼有誤)`);let f=h.map(t=>{let e=Be(t[2]),r=Be(t[3]),n=Be(t[6]),a=Be(t[5]),s=Be(t[8]),i=Be(t[9]),o=Be(t[12]),l=Be(t[11]);return{code:String(t[0]||"").trim(),name:String(t[1]||"").trim(),marginBuy:e,marginSell:r,marginCashRepay:Be(t[4]),marginPrevBalance:a,marginBalance:n,marginChange:n-a,marginLimit:Be(t[7]),shortSell:i,shortBuy:s,shortCashRepay:Be(t[10]),shortPrevBalance:l,shortBalance:o,shortChange:o-l,shortLimit:Be(t[13]),offset:Be(t[14]),note:String(t[15]||"").trim()}});return s&&console.log(`Fetched ${f.length} records.`),{source:"twse_margin",date:t,count:f.length,data:f}},fetchTpexMargin:async function(t,e,r={}){if(!lt(t)||!/^\d{8}$/.test(t))throw new Error(`日期參數無效:格式須為 YYYYMMDD (收到 "${t}")`);if(!Ue(t))throw new Error(`日期參數無效:不合法的日期 (${t})`);let n=it(r,"baseUrl");lt(n)||(n="https://www.tpex.org.tw"),n=n.replace(/\/+$/,"");let a=Ht(r,Ke),s=a.showLog,i=gt(e)?e.filter(Boolean):[],o=qe(t),l=`${n}/web/stock/margin_trading/margin_balance/margin_bal_result.php?l=zh-tw&d=${o}&o=json`;s&&(console.log(`Fetching TPEX margin data: ${t} (${o})`),console.log(`Target: ${i.length>0?i.join(", "):"All Market"}`),console.log(`URL: ${l}`));let u=await Nt(l,a),c=Array.isArray(u.tables)?u.tables:[],h=c.find(t=>it(t,"data.length",0)>0&&Array.isArray(t.fields)&&t.fields.some(t=>String(t).includes("資餘額"))&&t.fields.some(t=>String(t).includes("券餘額")))||c.find(t=>it(t,"data.length",0)>0);if(!h||!gt(it(h,"data")))throw new Error("TPEX margin API returned no data. Possibly a holiday or data not yet available.");let f=Array.isArray(h.fields)?h.fields:[];if(!String(f[6]||"").includes("資餘額")||!String(f[14]||"").includes("券餘額"))throw new Error(`TPEX 融資融券資料欄位佈局與預期不符(index6 應含「資餘額」實為「${f[6]??""}」、index14 應含「券餘額」實為「${f[14]??""}」);可能 API 格式變更,停止解析以免產生錯誤資料`);let g=h.data;if(i.length>0&&(g=g.filter(t=>i.includes(String(t[0]||"").trim())),0===g.length))throw new Error(`指定個股 ${i.join(",")} 不在上櫃融資融券資料中(可能為上市股或代碼有誤)`);let d=g.map(t=>{let e=Be(t[2]),r=Be(t[3]),n=Be(t[4]),a=Be(t[6]),s=Be(t[10]),i=Be(t[11]),o=Be(t[12]),l=Be(t[14]);return{code:String(t[0]||"").trim(),name:String(t[1]||"").trim(),marginBuy:r,marginSell:n,marginCashRepay:Be(t[5]),marginPrevBalance:e,marginBalance:a,marginChange:a-e,marginLimit:Be(t[9]),shortSell:i,shortBuy:o,shortCashRepay:Be(t[13]),shortPrevBalance:s,shortBalance:l,shortChange:l-s,shortLimit:Be(t[17]),offset:Be(t[18]),note:String(t[19]||"").trim()}});return s&&console.log(`Fetched ${d.length} records.`),{source:"tpex_margin",date:t,count:d.length,data:d}},fetchTwseT86:async function(t,e,r={}){if(!lt(t)||!/^\d{8}$/.test(t))throw new Error(`dateStr must be YYYYMMDD, got: ${t}`);if(!Ue(t))throw new Error(`dateStr 不是合法日期: ${t}`);let n=it(r,"baseUrl");lt(n)||(n="https://www.twse.com.tw"),n=n.replace(/\/+$/,"");let a=Ht(r,Ve),s=a.showLog,i=gt(e)?e:[],o=`${n}/rwd/zh/fund/T86?response=json&date=${t}&selectType=ALL`;s&&(console.log(`Fetching from: ${o}`),console.log(`Target: ${0===i.length?"All Market":i.join(", ")}`));let l=await Nt(o,a);if("OK"!==it(l,"stat"))throw new Error(`TWSE T86 API returned: ${it(l,"stat")}`);let u=it(l,"fields"),c=it(l,"data");if(!Array.isArray(c))throw new Error("TWSE T86: data not found in response.");if(!Array.isArray(u))throw new Error("TWSE T86: fields not found in response.");let h=c.map(t=>{let e={};return u.forEach((r,n)=>{let a=t[n];"string"==typeof a&&(a=a.trim()),e[r]=a}),e});if(i.length>0){let t=u.find(t=>String(t).includes("證券代號"));if(!t)throw new Error("無法篩選個股:API 回應中找不到證券代號欄位");h=h.filter(e=>i.includes(e[t]))}return s&&console.log(`Fetched ${h.length} records.`),{source:"twse",date:t,data:h}},fetchTpex3insti:async function(t,e,r={}){if(!lt(t)||!/^\d{8}$/.test(t))throw new Error(`dateStr must be YYYYMMDD, got: ${t}`);if(!Ue(t))throw new Error(`dateStr 不是合法日期: ${t}`);let n=it(r,"baseUrl");lt(n)||(n="https://www.tpex.org.tw"),n=n.replace(/\/+$/,"");let a=Ht(r,ze),s=a.showLog,i=gt(e)?e:[],o=`${n}/web/stock/3insti/daily_trade/3itrade_hedge_result.php?l=zh-tw&t=D&d=${qe(t)}&o=json`;s&&(console.log(`Fetching from: ${o}`),console.log(`Target: ${0===i.length?"All Market":i.join(", ")}`));let l=await Nt(o,a);if(!gt(it(l,"tables")))throw new Error("TPEX 3insti: tables not found in response. Possibly a holiday or no data.");let u=l.tables,c=u.find(t=>Array.isArray(t.fields)&&t.fields.some(t=>String(t).includes("代號"))&&t.fields.some(t=>String(t).includes("名稱")))||u[0],h=it(c,"fields"),f=it(c,"data");if(!Array.isArray(h)||!Array.isArray(f))throw new Error("TPEX 3insti: data/fields not found in table.");!function(t){if(t.length!==We.length)throw new Error(`TPEX 3insti: 欄數異常,預期 ${We.length} 得 ${t.length}(疑似 API 改版,請重新校準 TPEX_FIELD_MAP)`);if(!String(t[0]).includes("代號")||!String(t[1]).includes("名稱"))throw new Error(`TPEX 3insti: 前兩欄非「代號/名稱」(得「${t[0]}」「${t[1]}」,疑似 API 改版)`);if(!String(t[t.length-1]).includes("合計"))throw new Error(`TPEX 3insti: 末欄非「合計」(得「${t[t.length-1]}」,疑似 API 改版)`);let e=["買進股數","賣出股數","買賣超股數"];for(let r=2;r<t.length-1;r++){let n=e[(r-2)%3];if(String(t[r])!==n)throw new Error(`TPEX 3insti: 第 ${r} 欄預期「${n}」得「${t[r]}」(疑似 API 改版,欄序已變)`)}}(h);let g=f.map(t=>{let e={};return We.forEach((r,n)=>{let a=t[n];"string"==typeof a&&(a=a.trim()),e[r]=a}),e}).filter(t=>0===i.length||i.includes(t["代號"]));return s&&console.log(`Fetched ${g.length} records.`),{source:"tpex",date:t,data:g}},fetchTaifex:async function(t,e={}){if(!lt(t)||!/^\d{8}$/.test(t))throw new Error(`dateStr 須為 YYYYMMDD 字串,得到: ${t}`);if(!Ue(t))throw new Error(`dateStr 非合法日期: ${t}`);let r=it(e,"baseUrl");lt(r)||(r="https://www.taifex.com.tw"),r=r.replace(/\/+$/,"");let n=Ht(e,Re),a=n.showLog,s={baseUrl:r,showLog:a,optFetch:n},i=it(e,"interRequestDelayMs");i=Ct(i)?Lt(i):1e3;let o=`${t.substring(0,4)}/${t.substring(4,6)}/${t.substring(6,8)}`;a&&console.log(`Fetching TAIFEX data for ${t} (${o})`);let l=[],u=null,c=null,h=null;try{u=await async function(t,e){let r=`${e.baseUrl}/cht/3/futDataDown?down_type=1&queryStartDate=${t}&queryEndDate=${t}&commodity_id=TX`;e.showLog&&console.log(`Fetching futures data: ${r}`);let n=Fe(await Nt(r,{...e.optFetch,label:`${Re.label} Futures`}));if(0===n.length)throw new Error("台指期行情:無資料(可能非交易日)");let a=n.filter(t=>"TX"===t["契約"]&&!t["到期月份(週別)"].includes("/"));if(0===a.length)throw new Error("台指期行情:找不到 TX 合約資料");a.sort((t,e)=>t["到期月份(週別)"].trim().localeCompare(e["到期月份(週別)"].trim()));let s=a[0]["到期月份(週別)"].trim(),i=a.filter(t=>t["到期月份(週別)"].trim()===s),o=i.find(t=>"一般"===t["交易時段"]),l=i.find(t=>"盤後"===t["交易時段"]),u={contractMonth:s,open:null,high:null,low:null,close:null,settlement:null,volume:null,afterHoursClose:null,afterHoursSettlement:null,afterHoursVolume:null};return o&&(u.open=He(o["開盤價"]),u.high=He(o["最高價"]),u.low=He(o["最低價"]),u.close=He(o["收盤價"]),u.settlement=He(o["結算價"]),u.volume=He(o["成交量"])),l&&(u.afterHoursClose=He(l["收盤價"]),u.afterHoursSettlement=He(l["結算價"]),u.afterHoursVolume=He(l["成交量"])),e.showLog&&(console.log(` 台指期近月 (${s}): 開${u.open} 高${u.high} 低${u.low} 收${u.close} 結算${u.settlement} 量${u.volume}`),null!==u.afterHoursClose&&console.log(` 盤後: 收${u.afterHoursClose} 結算${u.afterHoursSettlement} 量${u.afterHoursVolume}`)),u}(o,s)}catch(t){let e=`台指期行情: ${it(t,"message",t)}`;a&&console.error(e),l.push(e)}await It(i);try{c=await async function(t,e){let r=`${e.baseUrl}/cht/3/futContractsDateDown?queryStartDate=${t}&queryEndDate=${t}&commodityId=TXF`;e.showLog&&console.log(`Fetching institutional data: ${r}`);let n=Fe(await Nt(r,{...e.optFetch,label:`${Re.label} Institutional`}));if(0===n.length)throw new Error("三大法人期貨未平倉:無資料(可能非交易日)");let a={};for(let t of n){let r=t["身份別"],n=Ye[r];n&&(a[n]={longContracts:He(t["多方未平倉口數"]),longAmount:He(t["多方未平倉契約金額(千元)"]),shortContracts:He(t["空方未平倉口數"]),shortAmount:He(t["空方未平倉契約金額(千元)"]),netContracts:He(t["多空未平倉口數淨額"]),netAmount:He(t["多空未平倉契約金額淨額(千元)"]),tradingLong:He(t["多方交易口數"]),tradingShort:He(t["空方交易口數"]),tradingNet:He(t["多空交易口數淨額"])},e.showLog&&console.log(` ${r}: 未平倉淨額 ${a[n].netContracts} 口`))}if(0===Object.keys(a).length)throw new Error("三大法人期貨未平倉:無法解析身份別(可能官方變更欄位用語)");return a}(o,s)}catch(t){let e=`三大法人: ${it(t,"message",t)}`;a&&console.error(e),l.push(e)}await It(i);try{h=await async function(t,e){let r=`${e.baseUrl}/cht/3/pcRatioDown?queryStartDate=${t}&queryEndDate=${t}`;e.showLog&&console.log(`Fetching P/C ratio: ${r}`);let n=Fe(await Nt(r,{...e.optFetch,label:`${Re.label} PCRatio`}));if(0===n.length)throw new Error("Put/Call Ratio:無資料(可能非交易日)");let a=n[0],s={putVolume:He(a["賣權成交量"]),callVolume:He(a["買權成交量"]),ratio:He(a["買賣權成交量比率%"]),putOpenInterest:He(a["賣權未平倉量"]),callOpenInterest:He(a["買權未平倉量"]),openInterestRatio:He(a["買賣權未平倉量比率%"])};return e.showLog&&console.log(` Put ${s.putVolume} / Call ${s.callVolume} = ${s.ratio}%`),s}(o,s)}catch(t){let e=`Put/Call Ratio: ${it(t,"message",t)}`;a&&console.error(e),l.push(e)}if(!(u||c||h)){let t=new Error(`所有資料抓取失敗: ${l.join("; ")}`);throw t.errors=l,t}return{date:t,futures:u?{tx:u}:null,institutional:c||null,pcRatio:h||null,errors:l}},fetchTwDataHoliday:async function(t,e={}){let r=it(e,"url");lt(r)||(r="https://openapi.twse.com.tw/v1/holidaySchedule/holidaySchedule");let n=Ht(e,Xe),a=await Nt(r,n),s=null;try{s=JSON.parse(a)}catch(t){throw new Error("API 回傳非 JSON 格式(可能為維護頁面或網路中介),請稍後再試")}if(!gt(s))throw new Error("API 回傳空陣列或格式異常");let i=s.filter(t=>!function(t){let e=String(it(t,"Name","")),r=String(it(t,"Description",""));return/交易日/.test(e)||/市場無交易/.test(e)||/開始交易/.test(r)||/最後交易/.test(r)}(t)).map(t=>{return{date:(e=it(t,"Date",""),`${parseInt(e.substring(0,e.length-4),10)+1911}${e.substring(e.length-4)}`),rocDate:it(t,"Date",""),name:it(t,"Name",""),weekday:it(t,"Weekday",""),description:String(it(t,"Description","")||"").replace(/<br\s*\/?>/gi,"").trim()};var e}),o=new Set,l=i.filter(t=>!o.has(t.date)&&(o.add(t.date),!0));l.sort((t,e)=>t.date.localeCompare(e.date));let u={dataYear:l.length>0?l[0].date.substring(0,4):null,totalHolidays:l.length,holidays:l};if(lt(t)&&/^\d{8}$/.test(t)){u.checkDate=t;let e=l.find(e=>e.date===t);u.isHoliday=!!e,u.holidayName=e?e.name:null}return u},fetchAisixiang:ge,fetchGuancha:{BASE_URL:pe,USER_AGENT:we,MAX_PAGES:50,KNOWN_TOPICS:ye,safeFilename:te,fetchAuthorsList:De,lookupAuthor:Me,lookupTopic:Ae,fetchAuthorArticles:async function(t={}){let e=$e(t),r=it(t,"name");lt(r)||(r="");let n=it(t,"slug");if(lt(n)||(n=""),!r&&!n)throw new Error("需要 name 或 slug");let a=n,s=r;if(!a){e.showLog&&process.stderr.write("[info] fetching authors index from / ...\n");let n=await De(t),i=Me(n,r);if(!i)return{status:"success",site:"guancha",mode:"author",query:r,fetched_at:(new Date).toISOString(),authors_count:n.length,count:0,items:[],message:`"${r}" 不在觀察者網作者索引中(共 ${n.length} 位)。尚無此作者文章。提醒:本函數不轉繁簡,呼叫端負責用站方登錄字形(簡體)。`};a=i.slug,s=i.name}let i=`${e.baseUrl}/${a}`,o=null;try{o=await ve(a,e)}catch(t){return{status:"error",site:"guancha",mode:"author",query:s||a,resolved:{slug:a,url:i,name:s},fetched_at:(new Date).toISOString(),reason:t.reason,error:t.message}}return{status:"success",site:"guancha",mode:"author",query:s||a,resolved:{slug:a,url:i,name:s,pages_fetched:o.pages_fetched},fetched_at:(new Date).toISOString(),count:o.items.length,items:o.items}},fetchKeywordArticles:async function(t,e={}){if(!lt(t))throw new Error("需要 keyword");return{status:"error",site:"guancha",mode:"keyword",query:t,fetched_at:(new Date).toISOString(),error:"unsupported-by-curl",message:"觀察者網搜尋 API(s.guancha.cn/main/search-v2)由 sojson.v4 混淆並走 MD5 簽名,本函數(純 curl 路徑)無法支援。如已知作者拼音 slug,請改用 fetchAuthorArticles({ slug });如已知主題 slug,請改用 fetchTopicArticles({ slug })。"}},fetchTitleArticles:async function(t,e={}){if(!lt(t))throw new Error("需要 keyword");return{status:"error",site:"guancha",mode:"title",query:t,fetched_at:(new Date).toISOString(),error:"unsupported-by-curl",message:"觀察者網無分「標題」與「全文」搜尋(兩者同源),搜尋 API 由 sojson.v4 混淆並走 MD5 簽名,本函數(純 curl 路徑)無法支援。如已知作者拼音 slug,請改用 fetchAuthorArticles({ slug })。"}},fetchTopicArticles:async function(t={}){let e=$e(t),r=it(t,"name");lt(r)||(r="");let n=it(t,"slug");if(lt(n)||(n=""),!r&&!n)throw new Error("需要 name 或 slug");let a=n,s=r;if(!a){let t=Ae(r);if(!t)return{status:"error",site:"guancha",mode:"topic",query:r,fetched_at:(new Date).toISOString(),topics_count:ye.length,error:"topic-not-in-table",message:`主題 "${r}" 不在已知主題對照表中(共 ${ye.length} 個)。觀察者網無公開主題清單頁,本函數採手工對照。建議直接傳 slug(拼音 slug)。本函數不自動轉向,請呼叫端決定是否重試。`};a=t.slug,s=t.name}let i=`${e.baseUrl}/${a}`,o=null;try{o=await ve(a,e)}catch(t){return{status:"error",site:"guancha",mode:"topic",query:s||a,resolved:{slug:a,url:i,name:s},fetched_at:(new Date).toISOString(),reason:t.reason,error:t.message}}return{status:"success",site:"guancha",mode:"topic",query:s||a,resolved:{slug:a,url:i,name:s,pages_fetched:o.pages_fetched},fetched_at:(new Date).toISOString(),count:o.items.length,items:o.items}},fetchArticle:async function(t={}){let e=$e(t),r=it(t,"url");if(!lt(r))throw new Error("需要 url");let n=null;try{n=await be(r,e)}catch(t){return{status:"error",site:"guancha",mode:"fetch",url:r,fetched_at:(new Date).toISOString(),error:t.message||"fetch failed"}}let a=function(t){let e=t.match(/<title>([\s\S]*?)<\/title>/i);return e?Jt(e[1].trim()):null}(n)||"",s=Qt(n,"content all-txt");if("观察者网"===a||"觀察者網"===a||!s)return{status:"error",site:"guancha",mode:"fetch",url:r,fetched_at:(new Date).toISOString(),error:"article-not-found",message:`無此文章(title="${a}",可能已下架或 URL 不正確)。`};let i=a.replace(/[_\-\s||]*(?:观察者网|觀察者網)\s*$/u,"").trim(),o=function(t){let e=t.match(/【([^】]{4,120})】/);return e?e[1].replace(/<[^>]+>/g,"").trim():null}(s)||"",l=function(t){let e=t.match(/<span[^>]*>(20\d{2}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2})<\/span>/);return e?e[1]:null}(n)||"",u=(new Date).toISOString().slice(0,10),c=Vt(s,{image:!0}),h=t=>String(t).replace(/"/g,'\\"'),f=`---\ntitle: "${h(i)}"\nsource: "${r}"\nauthor: "${h(o)}"\npublished: "${l}"\ncreated: ${u}\ndescription:\n---\n${c}\n`;return{status:"success",site:"guancha",mode:"fetch",url:r,title:i,author:o,published:l,chars:c.length,markdown:f}}}};return Qe});
6
+ !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e(require("child_process"),require("util"),require("cheerio"),require("playwright"),require("rss-parser")):"function"==typeof define&&define.amd?define(["child_process","util","cheerio","playwright","rss-parser"],e):(t="undefined"!=typeof globalThis?globalThis:t||self)["w-dwdata-hub"]=e(t.child_process,t.util,t.cheerio,t.playwright,t["rss-parser"])}(this,function(t,e,r,n,a){"use strict";function s(t){var e=Object.create(null);return t&&Object.keys(t).forEach(function(r){if("default"!==r){var n=Object.getOwnPropertyDescriptor(t,r);Object.defineProperty(e,r,n.get?n:{enumerable:!0,get:function(){return t[r]}})}}),e.default=t,Object.freeze(e)}var i=s(r),o=Array.isArray,l="object"==typeof global&&global&&global.Object===Object&&global,u="object"==typeof self&&self&&self.Object===Object&&self,c=l||u||Function("return this")(),h=c.Symbol,f=Object.prototype,g=f.hasOwnProperty,d=f.toString,m=h?h.toStringTag:void 0;var p=Object.prototype.toString;var w=h?h.toStringTag:void 0;function y(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":w&&w in Object(t)?function(t){var e=g.call(t,m),r=t[m];try{t[m]=void 0;var n=!0}catch(t){}var a=d.call(t);return n&&(e?t[m]=r:delete t[m]),a}(t):function(t){return p.call(t)}(t)}function $(t){return null!=t&&"object"==typeof t}function b(t){return"symbol"==typeof t||$(t)&&"[object Symbol]"==y(t)}var S=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,_=/^\w*$/;function v(t){var e=typeof t;return null!=t&&("object"==e||"function"==e)}var D,M=c["__core-js_shared__"],A=(D=/[^.]+$/.exec(M&&M.keys&&M.keys.IE_PROTO||""))?"Symbol(src)_1."+D:"";var x=Function.prototype.toString;var T=/^\[object .+?Constructor\]$/,E=Function.prototype,O=Object.prototype,k=E.toString,j=O.hasOwnProperty,C=RegExp("^"+k.call(j).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function L(t){if(!v(t)||(e=t,A&&A in e))return!1;var e,r=function(t){if(!v(t))return!1;var e=y(t);return"[object Function]"==e||"[object GeneratorFunction]"==e||"[object AsyncFunction]"==e||"[object Proxy]"==e}(t)?C:T;return r.test(function(t){if(null!=t){try{return x.call(t)}catch(t){}try{return t+""}catch(t){}}return""}(t))}function P(t,e){var r=function(t,e){return null==t?void 0:t[e]}(t,e);return L(r)?r:void 0}var U=P(Object,"create");var I=Object.prototype.hasOwnProperty;var R=Object.prototype.hasOwnProperty;function Y(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e<r;){var n=t[e];this.set(n[0],n[1])}}function N(t,e){return t===e||t!=t&&e!=e}function F(t,e){for(var r=t.length;r--;)if(N(t[r][0],e))return r;return-1}Y.prototype.clear=function(){this.__data__=U?U(null):{},this.size=0},Y.prototype.delete=function(t){var e=this.has(t)&&delete this.__data__[t];return this.size-=e?1:0,e},Y.prototype.get=function(t){var e=this.__data__;if(U){var r=e[t];return"__lodash_hash_undefined__"===r?void 0:r}return I.call(e,t)?e[t]:void 0},Y.prototype.has=function(t){var e=this.__data__;return U?void 0!==e[t]:R.call(e,t)},Y.prototype.set=function(t,e){var r=this.__data__;return this.size+=this.has(t)?0:1,r[t]=U&&void 0===e?"__lodash_hash_undefined__":e,this};var H=Array.prototype.splice;function q(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e<r;){var n=t[e];this.set(n[0],n[1])}}q.prototype.clear=function(){this.__data__=[],this.size=0},q.prototype.delete=function(t){var e=this.__data__,r=F(e,t);return!(r<0)&&(r==e.length-1?e.pop():H.call(e,r,1),--this.size,!0)},q.prototype.get=function(t){var e=this.__data__,r=F(e,t);return r<0?void 0:e[r][1]},q.prototype.has=function(t){return F(this.__data__,t)>-1},q.prototype.set=function(t,e){var r=this.__data__,n=F(r,t);return n<0?(++this.size,r.push([t,e])):r[n][1]=e,this};var z=P(c,"Map");function W(t,e){var r,n,a=t.__data__;return("string"==(n=typeof(r=e))||"number"==n||"symbol"==n||"boolean"==n?"__proto__"!==r:null===r)?a["string"==typeof e?"string":"hash"]:a.map}function B(t){var e=-1,r=null==t?0:t.length;for(this.clear();++e<r;){var n=t[e];this.set(n[0],n[1])}}B.prototype.clear=function(){this.size=0,this.__data__={hash:new Y,map:new(z||q),string:new Y}},B.prototype.delete=function(t){var e=W(this,t).delete(t);return this.size-=e?1:0,e},B.prototype.get=function(t){return W(this,t).get(t)},B.prototype.has=function(t){return W(this,t).has(t)},B.prototype.set=function(t,e){var r=W(this,t),n=r.size;return r.set(t,e),this.size+=r.size==n?0:1,this};function K(t,e){if("function"!=typeof t||null!=e&&"function"!=typeof e)throw new TypeError("Expected a function");var r=function(){var n=arguments,a=e?e.apply(this,n):n[0],s=r.cache;if(s.has(a))return s.get(a);var i=t.apply(this,n);return r.cache=s.set(a,i)||s,i};return r.cache=new(K.Cache||B),r}K.Cache=B;var G,X,Z,J=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,V=/\\(\\)?/g,Q=(G=function(t){var e=[];return 46===t.charCodeAt(0)&&e.push(""),t.replace(J,function(t,r,n,a){e.push(n?a.replace(V,"$1"):r||t)}),e},X=K(G,function(t){return 500===Z.size&&Z.clear(),t}),Z=X.cache,X),tt=Q;var et=h?h.prototype:void 0,rt=et?et.toString:void 0;function nt(t){if("string"==typeof t)return t;if(o(t))return function(t,e){for(var r=-1,n=null==t?0:t.length,a=Array(n);++r<n;)a[r]=e(t[r],r,t);return a}(t,nt)+"";if(b(t))return rt?rt.call(t):"";var e=t+"";return"0"==e&&1/t==-1/0?"-0":e}function at(t){return null==t?"":nt(t)}function st(t,e){return o(t)?t:function(t,e){if(o(t))return!1;var r=typeof t;return!("number"!=r&&"symbol"!=r&&"boolean"!=r&&null!=t&&!b(t))||_.test(t)||!S.test(t)||null!=e&&t in Object(e)}(t,e)?[t]:tt(at(t))}function it(t){if("string"==typeof t||b(t))return t;var e=t+"";return"0"==e&&1/t==-1/0?"-0":e}function ot(t,e,r){var n=null==t?void 0:function(t,e){for(var r=0,n=(e=st(e,t)).length;null!=t&&r<n;)t=t[it(e[r++])];return r&&r==n?t:void 0}(t,e);return void 0===n?r:n}function lt(t){return"[object String]"===Object.prototype.toString.call(t)}function ut(t){return!(!lt(t)||""===t)}function ct(t){return"[object Array]"===Object.prototype.toString.call(t)}function ht(t){return"[object Object]"===Object.prototype.toString.call(t)}function ft(t){return t!=t}function gt(t){return!!function(t){return"[object Undefined]"===Object.prototype.toString.call(t)}(t)||(!!function(t){return"[object Null]"===Object.prototype.toString.call(t)}(t)||(!!function(t){if(ht(t)){for(let e in t)return!1;return!0}return!1}(t)||(!!function(t){return!(!lt(t)||""!==t)}(t)||(!!function(t){return!!ct(t)&&0===t.length}(t)||!!ft(t)))))}function dt(t){return!!ct(t)&&(0!==t.length&&(1!==t.length||!gt(t[0])))}function mt(t){return!0===(e=t)||!1===e||$(e)&&"[object Boolean]"==y(e);var e}var pt=/\s/;var wt=/^\s+/;function yt(t){return t?t.slice(0,function(t){for(var e=t.length;e--&&pt.test(t.charAt(e)););return e}(t)+1).replace(wt,""):t}var $t=/^[-+]0x[0-9a-f]+$/i,bt=/^0b[01]+$/i,St=/^0o[0-7]+$/i,_t=parseInt;function vt(t){if("number"==typeof t)return t;if(b(t))return NaN;if(v(t)){var e="function"==typeof t.valueOf?t.valueOf():t;t=v(e)?e+"":e}if("string"!=typeof t)return 0===t?t:+t;t=yt(t);var r=bt.test(t);return r||St.test(t)?_t(t.slice(2),r?2:8):$t.test(t)?NaN:+t}var Dt=1/0;function Mt(t){return t?(t=vt(t))===Dt||t===-1/0?17976931348623157e292*(t<0?-1:1):t==t?t:0:0===t?t:0}function At(t){var e=Mt(t),r=e%1;return e==e?r?e-r:e:0}function xt(t){let e=!1;if(ut(t))e=!isNaN(Number(t));else if(function(t){return"[object Number]"===Object.prototype.toString.call(t)}(t)){if(ft(t))return!1;e=!0}return e}function Tt(t){if(!xt(t))return 0;return Mt(t)}function Et(t){return!!xt(t)&&(t=Tt(t),"number"==typeof(e=t)&&e==At(e));var e}var Ot=c.isFinite,kt=Math.min;var jt=function(t){var e=Math[t];return function(t,r){if(t=vt(t),(r=null==r?0:kt(At(r),292))&&Ot(t)){var n=(at(t)+"e").split("e");return+((n=(at(e(n[0]+"e"+(+n[1]+r)))+"e").split("e"))[0]+"e"+(+n[1]-r))}return e(t)}}("round"),Ct=jt;function Lt(t){if(!xt(t))return 0;t=Tt(t);let e=Ct(t);return"0"===String(e)?0:e}function Pt(t){if(!Et(t))return!1;return Lt(t)>0}function Ut(t){if(!Et(t))return!1;return Lt(t)>=0}function It(t=10){xt(t)||(t=10);let e=function(){let t,e,r=new Promise(function(){t=arguments[0],e=arguments[1]});return r.resolve=t,r.reject=e,r}();return setTimeout(function(){e.resolve()},t),e}let Rt=["ECONNRESET","ETIMEDOUT","ENOTFOUND","ECONNREFUSED","ECONNABORTED","EAI_AGAIN","EPIPE"];function Yt(t,e){let r=ot(t,"statusCode",null);if(Pt(r))return r>=500||429===r||e.includes(r);let n=ot(t,"cause.code",null)||ot(t,"code",null);if(ut(n)&&Rt.includes(n))return!0;let a=ot(t,"name","");if("AbortError"===a||"TimeoutError"===a)return!0;let s=String(ot(t,"cause.code","")||ot(t,"message",""));return!!/UND_ERR_(SOCKET|HEADERS_TIMEOUT|BODY_TIMEOUT|CONNECT_TIMEOUT)/.test(s)}async function Nt(t,e){let r=new AbortController,n=setTimeout(()=>{r.abort()},e.timeout);try{let n={method:e.method,headers:e.headers,signal:r.signal};null!==e.body&&(n.body=e.body);let a=await fetch(t,n);if(!a.ok){let e=new Error(`HTTP ${a.status} ${a.statusText}`.trim());throw e.statusCode=a.status,e.url=t,e}if("arrayBuffer"===e.responseType)return await a.arrayBuffer();if("text"===e.responseType){if(""!==e.encoding){let t=await a.arrayBuffer();return new TextDecoder(e.encoding).decode(t)}return await a.text()}let s=await a.text();try{return JSON.parse(s)}catch(t){throw new Error(`回傳非JSON格式(可能為維護頁面或網路中介): ${s.slice(0,100)}`)}}finally{clearTimeout(n)}}async function Ft(t,e={}){if(!ut(t))throw new Error(`url須為有效字串, 得到: ${t}`);let r=ot(e,"method");ut(r)||(r="GET");let n=ot(e,"headers");ht(n)||(n={}),ut(ot(n,"User-Agent"))||(n={"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",...n});let a=ot(e,"body",null);ut(a)||(a=null);let s=ot(e,"responseType");"text"!==s&&"arrayBuffer"!==s&&(s="json");let i=ot(e,"encoding");ut(i)||(i="");let o=ot(e,"timeout");o=Pt(o)?Lt(o):3e4;let l=ot(e,"maxRetries");l=Ut(l)?Lt(l):10;let u=ot(e,"baseDelayMs");u=Pt(u)?Lt(u):5e3;let c=ot(e,"maxDelayMs");c=Pt(c)?Lt(c):3e4;let h=ot(e,"retryStatus");dt(h)||(h=[]);let f=ot(e,"label");ut(f)||(f="fetchWithRetry");let g=ot(e,"showLog");mt(g)||(g=!0);let d={method:r,headers:n,body:a,responseType:s,encoding:i,timeout:o},m=null;for(let e=1;e<=l+1;e++)try{return await Nt(t,d)}catch(t){m=t;let r=l+1-e;if(!Yt(t,h)||r<=0)throw t;let n=Math.min(u*e,c);g&&console.warn(`[${f}][Retry ${e}/${l}] ${t.message} — 等待 ${n/1e3}s 後重試...`),await It(n)}throw m}function Ht(t,e,r,n){let a=ot(t,r);return Pt(a)?Lt(a):(a=ot(e,r),Pt(a)?Lt(a):n)}function qt(t={},e={}){let r=ot(t,"maxRetries");Ut(r)||(r=ot(e,"maxRetries")),r=Ut(r)?Lt(r):10;let n=ot(t,"showLog");mt(n)||(n=ot(e,"showLog")),mt(n)||(n=!0);let a={timeout:Ht(t,e,"timeout",3e4),maxRetries:r,baseDelayMs:Ht(t,e,"baseDelayMs",5e3),maxDelayMs:Ht(t,e,"maxDelayMs",3e4),showLog:n};return ut(ot(e,"responseType"))&&(a.responseType=e.responseType),ut(ot(e,"encoding"))&&(a.encoding=e.encoding),ht(ot(e,"headers"))&&(a.headers=e.headers),dt(ot(e,"retryStatus"))&&(a.retryStatus=e.retryStatus),ut(ot(e,"label"))&&(a.label=e.label),a}"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self&&self;function zt(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var Wt={exports:{}};!function(t){t.exports=function(){var t=1e3,e=6e4,r=36e5,n="millisecond",a="second",s="minute",i="hour",o="day",l="week",u="month",c="quarter",h="year",f="date",g="Invalid Date",d=/^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[Tt\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/,m=/\[([^\]]+)]|YYYY|YY|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g,p={name:"en",weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),ordinal:function(t){var e=["th","st","nd","rd"],r=t%100;return"["+t+(e[(r-20)%10]||e[r]||e[0])+"]"}},w=function(t,e,r){var n=String(t);return!n||n.length>=e?t:""+Array(e+1-n.length).join(r)+t},y={s:w,z:function(t){var e=-t.utcOffset(),r=Math.abs(e),n=Math.floor(r/60),a=r%60;return(e<=0?"+":"-")+w(n,2,"0")+":"+w(a,2,"0")},m:function t(e,r){if(e.date()<r.date())return-t(r,e);var n=12*(r.year()-e.year())+(r.month()-e.month()),a=e.clone().add(n,u),s=r-a<0,i=e.clone().add(n+(s?-1:1),u);return+(-(n+(r-a)/(s?a-i:i-a))||0)},a:function(t){return t<0?Math.ceil(t)||0:Math.floor(t)},p:function(t){return{M:u,y:h,w:l,d:o,D:f,h:i,m:s,s:a,ms:n,Q:c}[t]||String(t||"").toLowerCase().replace(/s$/,"")},u:function(t){return void 0===t}},$="en",b={};b[$]=p;var S="$isDayjsObject",_=function(t){return t instanceof A||!(!t||!t[S])},v=function t(e,r,n){var a;if(!e)return $;if("string"==typeof e){var s=e.toLowerCase();b[s]&&(a=s),r&&(b[s]=r,a=s);var i=e.split("-");if(!a&&i.length>1)return t(i[0])}else{var o=e.name;b[o]=e,a=o}return!n&&a&&($=a),a||!n&&$},D=function(t,e){if(_(t))return t.clone();var r="object"==typeof e?e:{};return r.date=t,r.args=arguments,new A(r)},M=y;M.l=v,M.i=_,M.w=function(t,e){return D(t,{locale:e.$L,utc:e.$u,x:e.$x,$offset:e.$offset})};var A=function(){function p(t){this.$L=v(t.locale,null,!0),this.parse(t),this.$x=this.$x||t.x||{},this[S]=!0}var w=p.prototype;return w.parse=function(t){this.$d=function(t){var e=t.date,r=t.utc;if(null===e)return new Date(NaN);if(M.u(e))return new Date;if(e instanceof Date)return new Date(e);if("string"==typeof e&&!/Z$/i.test(e)){var n=e.match(d);if(n){var a=n[2]-1||0,s=(n[7]||"0").substring(0,3);return r?new Date(Date.UTC(n[1],a,n[3]||1,n[4]||0,n[5]||0,n[6]||0,s)):new Date(n[1],a,n[3]||1,n[4]||0,n[5]||0,n[6]||0,s)}}return new Date(e)}(t),this.init()},w.init=function(){var t=this.$d;this.$y=t.getFullYear(),this.$M=t.getMonth(),this.$D=t.getDate(),this.$W=t.getDay(),this.$H=t.getHours(),this.$m=t.getMinutes(),this.$s=t.getSeconds(),this.$ms=t.getMilliseconds()},w.$utils=function(){return M},w.isValid=function(){return!(this.$d.toString()===g)},w.isSame=function(t,e){var r=D(t);return this.startOf(e)<=r&&r<=this.endOf(e)},w.isAfter=function(t,e){return D(t)<this.startOf(e)},w.isBefore=function(t,e){return this.endOf(e)<D(t)},w.$g=function(t,e,r){return M.u(t)?this[e]:this.set(r,t)},w.unix=function(){return Math.floor(this.valueOf()/1e3)},w.valueOf=function(){return this.$d.getTime()},w.startOf=function(t,e){var r=this,n=!!M.u(e)||e,c=M.p(t),g=function(t,e){var a=M.w(r.$u?Date.UTC(r.$y,e,t):new Date(r.$y,e,t),r);return n?a:a.endOf(o)},d=function(t,e){return M.w(r.toDate()[t].apply(r.toDate("s"),(n?[0,0,0,0]:[23,59,59,999]).slice(e)),r)},m=this.$W,p=this.$M,w=this.$D,y="set"+(this.$u?"UTC":"");switch(c){case h:return n?g(1,0):g(31,11);case u:return n?g(1,p):g(0,p+1);case l:var $=this.$locale().weekStart||0,b=(m<$?m+7:m)-$;return g(n?w-b:w+(6-b),p);case o:case f:return d(y+"Hours",0);case i:return d(y+"Minutes",1);case s:return d(y+"Seconds",2);case a:return d(y+"Milliseconds",3);default:return this.clone()}},w.endOf=function(t){return this.startOf(t,!1)},w.$set=function(t,e){var r,l=M.p(t),c="set"+(this.$u?"UTC":""),g=(r={},r[o]=c+"Date",r[f]=c+"Date",r[u]=c+"Month",r[h]=c+"FullYear",r[i]=c+"Hours",r[s]=c+"Minutes",r[a]=c+"Seconds",r[n]=c+"Milliseconds",r)[l],d=l===o?this.$D+(e-this.$W):e;if(l===u||l===h){var m=this.clone().set(f,1);m.$d[g](d),m.init(),this.$d=m.set(f,Math.min(this.$D,m.daysInMonth())).$d}else g&&this.$d[g](d);return this.init(),this},w.set=function(t,e){return this.clone().$set(t,e)},w.get=function(t){return this[M.p(t)]()},w.add=function(n,c){var f,g=this;n=Number(n);var d=M.p(c),m=function(t){var e=D(g);return M.w(e.date(e.date()+Math.round(t*n)),g)};if(d===u)return this.set(u,this.$M+n);if(d===h)return this.set(h,this.$y+n);if(d===o)return m(1);if(d===l)return m(7);var p=(f={},f[s]=e,f[i]=r,f[a]=t,f)[d]||1,w=this.$d.getTime()+n*p;return M.w(w,this)},w.subtract=function(t,e){return this.add(-1*t,e)},w.format=function(t){var e=this,r=this.$locale();if(!this.isValid())return r.invalidDate||g;var n=t||"YYYY-MM-DDTHH:mm:ssZ",a=M.z(this),s=this.$H,i=this.$m,o=this.$M,l=r.weekdays,u=r.months,c=r.meridiem,h=function(t,r,a,s){return t&&(t[r]||t(e,n))||a[r].slice(0,s)},f=function(t){return M.s(s%12||12,t,"0")},d=c||function(t,e,r){var n=t<12?"AM":"PM";return r?n.toLowerCase():n};return n.replace(m,function(t,n){return n||function(t){switch(t){case"YY":return String(e.$y).slice(-2);case"YYYY":return M.s(e.$y,4,"0");case"M":return o+1;case"MM":return M.s(o+1,2,"0");case"MMM":return h(r.monthsShort,o,u,3);case"MMMM":return h(u,o);case"D":return e.$D;case"DD":return M.s(e.$D,2,"0");case"d":return String(e.$W);case"dd":return h(r.weekdaysMin,e.$W,l,2);case"ddd":return h(r.weekdaysShort,e.$W,l,3);case"dddd":return l[e.$W];case"H":return String(s);case"HH":return M.s(s,2,"0");case"h":return f(1);case"hh":return f(2);case"a":return d(s,i,!0);case"A":return d(s,i,!1);case"m":return String(i);case"mm":return M.s(i,2,"0");case"s":return String(e.$s);case"ss":return M.s(e.$s,2,"0");case"SSS":return M.s(e.$ms,3,"0");case"Z":return a}return null}(t)||a.replace(":","")})},w.utcOffset=function(){return 15*-Math.round(this.$d.getTimezoneOffset()/15)},w.diff=function(n,f,g){var d,m=this,p=M.p(f),w=D(n),y=(w.utcOffset()-this.utcOffset())*e,$=this-w,b=function(){return M.m(m,w)};switch(p){case h:d=b()/12;break;case u:d=b();break;case c:d=b()/3;break;case l:d=($-y)/6048e5;break;case o:d=($-y)/864e5;break;case i:d=$/r;break;case s:d=$/e;break;case a:d=$/t;break;default:d=$}return g?d:M.a(d)},w.daysInMonth=function(){return this.endOf(u).$D},w.$locale=function(){return b[this.$L]},w.locale=function(t,e){if(!t)return this.$L;var r=this.clone(),n=v(t,e,!0);return n&&(r.$L=n),r},w.clone=function(){return M.w(this.$d,this)},w.toDate=function(){return new Date(this.valueOf())},w.toJSON=function(){return this.isValid()?this.toISOString():null},w.toISOString=function(){return this.$d.toISOString()},w.toString=function(){return this.$d.toUTCString()},p}(),x=A.prototype;return D.prototype=x,[["$ms",n],["$s",a],["$m",s],["$H",i],["$W",o],["$M",u],["$y",h],["$D",f]].forEach(function(t){x[t[1]]=function(e){return this.$g(e,t[0],t[1])}}),D.extend=function(t,e){return t.$i||(t(e,A,D),t.$i=!0),D},D.locale=v,D.isDayjs=_,D.unix=function(t){return D(1e3*t)},D.en=b[$],D.Ls=b,D.p={},D}()}(Wt);var Bt=zt(Wt.exports),Kt={exports:{}};!function(t){var e,r,n;t.exports=(e="minute",r=/[+-]\d\d(?::?\d\d)?/g,n=/([+-]|\d\d)/g,function(t,a,s){var i=a.prototype;s.utc=function(t){return new a({date:t,utc:!0,args:arguments})},i.utc=function(t){var r=s(this.toDate(),{locale:this.$L,utc:!0});return t?r.add(this.utcOffset(),e):r},i.local=function(){return s(this.toDate(),{locale:this.$L,utc:!1})};var o=i.parse;i.parse=function(t){t.utc&&(this.$u=!0),this.$utils().u(t.$offset)||(this.$offset=t.$offset),o.call(this,t)};var l=i.init;i.init=function(){if(this.$u){var t=this.$d;this.$y=t.getUTCFullYear(),this.$M=t.getUTCMonth(),this.$D=t.getUTCDate(),this.$W=t.getUTCDay(),this.$H=t.getUTCHours(),this.$m=t.getUTCMinutes(),this.$s=t.getUTCSeconds(),this.$ms=t.getUTCMilliseconds()}else l.call(this)};var u=i.utcOffset;i.utcOffset=function(t,a){var s=this.$utils().u;if(s(t))return this.$u?0:s(this.$offset)?u.call(this):this.$offset;if("string"==typeof t&&(t=function(t){void 0===t&&(t="");var e=t.match(r);if(!e)return null;var a=(""+e[0]).match(n)||["-",0,0],s=a[0],i=60*+a[1]+ +a[2];return 0===i?0:"+"===s?i:-i}(t),null===t))return this;var i=Math.abs(t)<=16?60*t:t;if(0===i)return this.utc(a);var o=this.clone();if(a)return o.$offset=i,o.$u=!1,o;var l=this.$u?this.toDate().getTimezoneOffset():-1*this.utcOffset();return(o=this.local().add(i+l,e)).$offset=i,o.$x.$localOffset=l,o};var c=i.format;i.format=function(t){var e=t||(this.$u?"YYYY-MM-DDTHH:mm:ss[Z]":"");return c.call(this,e)},i.valueOf=function(){var t=this.$utils().u(this.$offset)?0:this.$offset+(this.$x.$localOffset||this.$d.getTimezoneOffset());return this.$d.valueOf()-6e4*t},i.isUTC=function(){return!!this.$u},i.toISOString=function(){return this.toDate().toISOString()},i.toString=function(){return this.toDate().toUTCString()};var h=i.toDate;i.toDate=function(t){return"s"===t&&this.$offset?s(this.format("YYYY-MM-DD HH:mm:ss:SSS")).toDate():h.call(this)};var f=i.diff;i.diff=function(t,e,r){if(t&&this.$u===t.$u)return f.call(this,t,e,r);var n=this.local(),a=s(t).local();return f.call(n,a,e,r)}})}(Kt);var Gt=zt(Kt.exports);Bt.extend(Gt);let Xt=/^[^T:]*$/;function Zt(t){let e=null,r=!1;if("number"==typeof t){if(0===t)return"";e=Bt.unix(t)}else if(t instanceof Date)e=Bt(t);else{if(!ut(t))return"";e=Bt(t),r=Xt.test(t)}return e.isValid()?e.utcOffset(8,r).format("YYYY-MM-DD HH:mm:ss"):""}let Jt={timeout:3e4,maxRetries:5,baseDelayMs:3e3,maxDelayMs:15e3,label:"fetch-ai-news-aggregator"};let Vt={nbsp:" ",amp:"&",lt:"<",gt:">",quot:'"',apos:"'",hellip:"…",mdash:"—",ndash:"–",middot:"·",ldquo:'"',rdquo:'"',lsquo:"‘",rsquo:"’",laquo:"«",raquo:"»",copy:"©",reg:"®"};function Qt(t){return lt(t)?t.replace(/&([a-zA-Z]+);/g,(t,e)=>void 0!==Vt[e]?Vt[e]:t).replace(/&#(\d+);/g,(t,e)=>String.fromCodePoint(Number(e))).replace(/&#x([\da-fA-F]+);/g,(t,e)=>String.fromCodePoint(parseInt(e,16))):""}function te(t,e={}){if(!lt(t))return"";let r=ot(e,"image");mt(r)||(r=!1);let n=t;return n=n.replace(/<script[\s\S]*?<\/script>/gi,""),n=n.replace(/<style[\s\S]*?<\/style>/gi,""),n=n.replace(/<!--[\s\S]*?-->/g,""),r&&(n=n.replace(/<img[^>]*src="([^"]+)"[^>]*\/?>/gi,(t,e)=>`![](${e})`)),n=n.replace(/<h[1-6][^>]*>([\s\S]*?)<\/h[1-6]>/gi,"\n\n**$1**\n\n"),n=n.replace(/<\/?(?:strong|b)(?:\s[^>]*)?>/gi,"**"),n=n.replace(/<\/?(?:em|i)(?:\s[^>]*)?>/gi,"*"),n=n.replace(/<br\s*\/?>/gi,"\n"),n=n.replace(/<a\s+[^>]*href="([^"]+)"[^>]*>([\s\S]*?)<\/a>/gi,(t,e,r)=>{let n=r.replace(/<[^>]+>/g,"").trim();return n?`[${n}](${e})`:""}),n=n.replace(/<p(?:\s[^>]*)?>/gi,""),n=n.replace(/<\/p>/gi,"\n\n"),n=n.replace(/<\/?(?:div|span|section|article|font|u)(?:\s[^>]*)?>/gi,""),n=n.replace(/<[^>]+>/g,""),n=Qt(n),n=n.split("\n").map(t=>t.replace(/[ \t\u00A0]+/g," ").trimEnd()).join("\n"),n=n.replace(/\n{3,}/g,"\n\n").replace(/\*\*\s*\*\*/g,""),n.trim()}function ee(t,e){if(!lt(t))return null;if(!ut(e))return null;let r=`<div class="${e}"`,n=t.indexOf(r);if(-1===n)return null;let a=t.indexOf(">",n);if(-1===a)return null;let s=a+1,i=s,o=1;for(;o>0&&i<t.length;){let e=t.indexOf("<div",i),r=t.indexOf("</div>",i);if(-1===r)return null;if(-1!==e&&e<r)o++,i=e+4;else{if(o--,0===o)return t.slice(s,r);i=r+6}}return null}function re(t){return lt(t)||(t=String(null==t?"":t)),t.replace(/[\\/:*?"<>|]/g,"_").slice(0,200)}let ne="https://www.aisixiang.com",ae="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0 Safari/537.36",se={responseType:"text",headers:{"User-Agent":ae,"Accept-Language":"zh-CN,zh;q=0.9"},timeout:3e4,maxRetries:5,baseDelayMs:5e3,maxDelayMs:3e4,label:"fetch-aisixiang"};function ie(t={}){let e=ot(t,"baseUrl");ut(e)||(e=ne),e=e.replace(/\/+$/,"");let r=qt(t,se),n=ot(t,"pageDelayMs");n=Ut(n)?Lt(n):1e3;let a=ot(t,"maxPages");return a=Pt(a)?Math.min(Lt(a),50):50,{baseUrl:e,showLog:r.showLog,pageDelayMs:n,maxPages:a,optFetch:r}}function oe(t,e){let r=ee(t,"search_list");if(null===r)return[];let n,a=[],s=new Set,i=/href="\/data\/(\d+)\.html"[^>]*title="([^"]+)"/g;for(;null!==(n=i.exec(r));){if(s.has(n[1]))continue;s.add(n[1]);let t=n[2],r=t.indexOf(":");a.push({aid:n[1],url:`${e}/data/${n[1]}.html`,title:r>0?t.slice(r+1).trim():t.trim(),author:r>0?t.slice(0,r).trim():""})}return a}function le(t,e){let r,n=t.match(/([\s\S]+?)<div class="list_page">/),a=n?n[1]:t,s=[],i=new Set,o=/<a\s+href="\/data\/(\d+)\.html"[^>]*>([^<]+)<\/a>/g;for(;null!==(r=o.exec(a));){if(i.has(r[1]))continue;i.add(r[1]);let t=r[2].trim(),n=t.indexOf(":");s.push({aid:r[1],url:`${e}/data/${r[1]}.html`,title:n>0?t.slice(n+1).trim():t,author:n>0?t.slice(0,n).trim():""})}return s}function ue(t){let e=t.match(/<div class="list_page">([\s\S]+?)<\/div>/);if(!e)return 1;let r=[...e[1].matchAll(/page=(\d+)/g)].map(t=>Number(t[1]));return r.length?Math.max(...r):1}async function ce(t,e,r){let n=[],a=new Set,s=1,i=0;for(let o=1;o<=r.maxPages;o++){let l=t(o);r.showLog&&process.stderr.write(`[info] fetching page ${o}${s>1?`/${s}`:""} ...\n`);let u=await Ft(l,r.optFetch);i++,1===o&&(s=ue(u));let c=e(u,r.baseUrl).filter(t=>!a.has(t.aid));if(0===c.length){r.showLog&&process.stderr.write(`[info] page ${o} 無新項目,停止翻頁\n`);break}for(let t of c)a.add(t.aid);if(n.push(...c),o>=s)break;await It(r.pageDelayMs)}return{items:n,total_pages:s,pages_fetched:i}}async function he(t={}){let e=ie(t),r=[...(await Ft(`${e.baseUrl}/thinktank/`,e.optFetch)).matchAll(/href="\/thinktank\/([^"]+?)\.html"[^>]*>([^<]+)</g)],n=new Map;for(let[,t,e]of r){let r=t.toLowerCase();if(n.has(r))continue;let a=e.split(/[,、]/)[0].trim();!a||a.length>30||n.set(r,{slug:t,name:a})}return[...n.values()]}function fe(t,e){return Array.isArray(t)&&t.find(t=>t.name===e)||null}async function ge(t={}){let e=ie(t),r=await Ft(`${e.baseUrl}/zhuanti/`,e.optFetch),n=[{name:"学科",start:r.indexOf("<h3>学科关键词</h3>")},{name:"事件",start:r.indexOf("<h3>事件关键词</h3>")},{name:"人物",start:r.indexOf("<h3>人物关键词</h3>")}].filter(t=>t.start>=0).sort((t,e)=>t.start-e.start);n.push({name:null,start:r.length});let a=new Set,s=[];for(let t=0;t<n.length-1;t++){let e,i=r.slice(n[t].start,n[t+1].start),o=/href="\/zhuanti\/(\d+)\.html"[^>]*>([^<]+)</g;for(;null!==(e=o.exec(i));){if(a.has(e[1]))continue;a.add(e[1]);let r=e[2].trim().replace(/^\[|\]$/g,"").trim();!r||r.length>50||s.push({id:e[1],name:r,category:n[t].name})}}return s}function de(t,e){return Array.isArray(t)&&t.find(t=>t.name===e)||null}let me={BASE_URL:ne,USER_AGENT:ae,MAX_PAGES:50,safeFilename:re,fetchAuthorsList:he,lookupAuthor:fe,fetchTopicsList:ge,lookupTopic:de,fetchAuthorArticles:async function(t={}){let e=ie(t),r=ot(t,"name");ut(r)||(r="");let n=ot(t,"slug");if(ut(n)||(n=""),!r&&!n)throw new Error("需要 name 或 slug");let a=null,s=r,i=n;if(i)a={slug:i,url:`${e.baseUrl}/thinktank/${i}.html`};else{e.showLog&&process.stderr.write("[info] fetching authors list from /thinktank/ ...\n");let n=await he(t),o=fe(n,r);if(!o)return{status:"success",site:"aisixiang",mode:"author",query:r,fetched_at:(new Date).toISOString(),authors_count:n.length,count:0,items:[],message:`"${r}" 不在愛思想專欄作者清單中(共 ${n.length} 位)。尚無此作者文章(此為查詢成功的真實結果、0 筆,非抓取失敗)。提醒:本函數不轉簡繁,呼叫端負責用站方登錄字形(通常是簡體)。`};i=o.slug,s=s||o.name,a={slug:i,url:`${e.baseUrl}/thinktank/${i}.html`,name:o.name}}let o=function(t,e){let r=["论文","时评","随笔","著作","演讲","读书","访谈","未分类"],n=[];for(let e of r){let r,a=new RegExp(`<h3>${e}<\\/h3>`,"g");for(;null!==(r=a.exec(t));)n.push({cat:e,pos:r.index})}n.sort((t,e)=>t.pos-e.pos),n.push({cat:null,pos:t.length});let a=[];for(let r=0;r<n.length-1;r++){let s,{cat:i,pos:o}=n[r],l=t.slice(o,n[r+1].pos),u=/<a\s+href="\/data\/(\d+)\.html"[^>]*>([\s\S]*?)<\/a>/g;for(;null!==(s=u.exec(l));){let t=s[2].replace(/<[^>]+>/g,"").trim();t&&a.push({aid:s[1],url:`${e}/data/${s[1]}.html`,title:t,category:i})}}return a}(await Ft(a.url,e.optFetch),e.baseUrl),l={status:"success",site:"aisixiang",mode:"author",query:s||i,resolved:a,fetched_at:(new Date).toISOString(),count:o.length,items:o};return 0===o.length&&(l.message=`已命中愛思想作者欄頁(${a.url})但該欄頁目前 0 篇文章。此為查詢成功的真實結果(非抓取失敗);若 slug 為手動指定,請確認 slug 是否正確。`),l},fetchKeywordArticles:async function(t,e={}){if(!ut(t))throw new Error("需要 keyword");let r=ie(e),n=e=>`${r.baseUrl}/data/search?searchfield=keywords&keywords=${encodeURIComponent(t)}&page=${e}`,{items:a,total_pages:s,pages_fetched:i}=await ce(n,oe,r);return 0===a.length?{status:"success",site:"aisixiang",mode:"keyword",query:t,resolved:{search_url:n(1)},fetched_at:(new Date).toISOString(),count:0,items:[],message:`關鍵字 "${t}" 在愛思想無相關文章。提醒:站方搜尋只認簡體,呼叫端負責簡體化;若已是簡體仍 0 筆,該主題可能無 tag 索引。`}:{status:"success",site:"aisixiang",mode:"keyword",query:t,resolved:{search_url:n(1),total_pages:s,pages_fetched:i},fetched_at:(new Date).toISOString(),count:a.length,items:a}},fetchTitleArticles:async function(t,e={}){if(!ut(t))throw new Error("需要 keyword");let r=ie(e),n=e=>`${r.baseUrl}/data/search?searchfield=title&keywords=${encodeURIComponent(t)}&page=${e}`,{items:a,total_pages:s,pages_fetched:i}=await ce(n,oe,r);return 0===a.length?{status:"success",site:"aisixiang",mode:"title",query:t,resolved:{search_url:n(1)},fetched_at:(new Date).toISOString(),count:0,items:[],message:`標題關鍵字 "${t}" 在愛思想無相關文章。提醒:站方搜尋只認簡體,呼叫端負責簡體化。`}:{status:"success",site:"aisixiang",mode:"title",query:t,resolved:{search_url:n(1),total_pages:s,pages_fetched:i},fetched_at:(new Date).toISOString(),count:a.length,items:a}},fetchTopicArticles:async function(t={}){let e=ie(t),r=ot(t,"keyword");ut(r)||(r="");let n=ot(t,"id");if(ut(n)||(n=""),!r&&!n)throw new Error("需要 keyword 或 id");let a=n,s=r,i=null;if(a)i={id:a,url:`${e.baseUrl}/zhuanti/${a}.html`};else{e.showLog&&process.stderr.write("[info] fetching topics list from /zhuanti/ ...\n");let n=await ge(t),o=de(n,r);if(!o)return{status:"success",site:"aisixiang",mode:"topic",query:r,fetched_at:(new Date).toISOString(),topics_count:n.length,count:0,items:[],message:`"${r}" 不在愛思想策展主題清單中(共 ${n.length} 個主題)。建議改用 fetchKeywordArticles('${r}') 查 keyword tag 結果。本函數不自動轉向,請呼叫端決定是否重試。`};a=o.id,s=o.name,i={id:a,name:o.name,category:o.category,url:`${e.baseUrl}/zhuanti/${a}.html`}}let{items:o,total_pages:l,pages_fetched:u}=await ce(t=>`${e.baseUrl}/zhuanti/${a}.html?page=${t}`,le,e),c={status:"success",site:"aisixiang",mode:"topic",query:s||a,resolved:{...i,total_pages:l,pages_fetched:u},fetched_at:(new Date).toISOString(),count:o.length,items:o};return 0===o.length&&(c.message=`已命中愛思想策展主題(${i.url})但該主題頁目前 0 篇文章。此為查詢成功的真實結果(非抓取失敗);若需更多結果可改用 fetchKeywordArticles 查 keyword tag。`),c},fetchArticle:async function(t={}){let e=ie(t),r=ot(t,"aid");ut(r)||(r="");let n=ot(t,"url");ut(n)||(n="");let a=r?`${e.baseUrl}/data/${r}.html`:n;if(!a)throw new Error("需要 aid 或 url");let s=await Ft(a,e.optFetch),i=function(t){let e=t.match(/<title>([\s\S]*?)<\/title>/i);return e?Qt(e[1].trim()):null}(s),o=ee(s,"article-content");if(!i||!o)throw new Error(`解析失敗:title=${!!i}, content=${!!o}`);let l=te(o),u=i.replace(/[_\-\s]*(?:_)?(?:爱思想|愛思想)\s*$/u,"").trim(),c=`---\ntitle: "${u}"\nsource: "${a}"\nauthor:\npublished:\ncreated: ${(new Date).toISOString().slice(0,10)}\ndescription:\n---\n${l}\n`;return{status:"success",site:"aisixiang",mode:"fetch",url:a,title:u,chars:l.length,markdown:c}}},pe={timeout:3e4,maxRetries:10,baseDelayMs:5e3,maxDelayMs:3e4,retryStatus:[403],label:"fetch-cnyes"};function we(t,e,r){return ut(t)?function(t){if(!ut(t))return!1;try{let e=new URL(t);return"http:"===e.protocol||"https:"===e.protocol}catch{return!1}}(t)?null:{status:"error",url:t,message:"invalid url (must be http/https)",reason:"invalid-url",method:e,fetchedAt:r,attempts:0}:{status:"error",url:String(t),message:"url is required (string)",reason:"invalid-url",method:e,fetchedAt:r,attempts:0}}function ye(t){return Ut(t)?Math.min(3e3*t,15e3):3e3}let $e="curl",be=e.promisify(t.execFile);async function Se(t,e={}){let r=(new Date).toISOString(),n=we(t,$e,r);if(n)return n;let a=ot(e,"timeoutMs",null);a=Pt(a)?Lt(a):15e3;let s=ot(e,"maxRetries",null);s=Ut(s)?Lt(s):5;let i=ot(e,"userAgent",null);ut(i)||(i="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36");let o=ot(e,"referer",null);ut(o)||(o="https://www.google.com/");let l=ot(e,"acceptLanguage",null);ut(l)||(l="en-US,en;q=0.9,zh-TW;q=0.8");let u="",c="",h=0;for(let e=1;e<=s+1;e++)try{let{stdout:n}=await be("curl",["-s","-L","--compressed","--max-time",String(Math.ceil(a/1e3)),"--write-out","\n%{http_code}","-H","User-Agent: "+i,"-H","Accept: text/html,application/xhtml+xml","-H","Accept-Language: "+l,"-H","Referer: "+o,t],{encoding:"utf8",timeout:a+5e3,maxBuffer:10485760,windowsHide:!0}),f=n.trimEnd().split("\n"),g=parseInt(f.pop(),10)||0,d=f.join("\n");if(h=g,g>=500||429===g){if(u="http-error",c=`HTTP ${g}`,e<=s){let r=ye(e);process.stderr.write(`[fetchWebByCurl] HTTP ${g} ${t},等 ${r}ms 後重試 (${e}/${s})\n`),await It(r);continue}return{status:"error",url:t,message:c,reason:u,httpCode:g,method:$e,fetchedAt:r,attempts:e}}return g>=400?{status:"error",url:t,message:`HTTP ${g}`,reason:"http-error",httpCode:g,method:$e,fetchedAt:r,attempts:e}:!d||d.length<100?{status:"error",url:t,message:`response too short (${d?d.length:0} chars)`,reason:"empty-response",httpCode:g,method:$e,fetchedAt:r,attempts:e}:{status:"success",url:t,html:d,htmlLength:d.length,httpCode:g,method:$e,fetchedAt:r,attempts:e}}catch(n){if(u="curl-error",c=n.message||String(n),e<=s){let t=ye(e);process.stderr.write(`[fetchWebByCurl] curl error: ${c},等 ${t}ms 後重試 (${e}/${s})\n`),await It(t);continue}return{status:"error",url:t,message:c,reason:u,httpCode:h||void 0,method:$e,fetchedAt:r,attempts:e}}return{status:"error",url:t,message:c||"max retries exceeded",reason:u||"curl-error",method:$e,fetchedAt:r,attempts:s+1}}let _e="https://www.guancha.cn",ve="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",De=[{slug:"CaiJing",name:"财经"},{slug:"economy",name:"财经-大頻道"},{slug:"JunShi",name:"军事"},{slug:"military-affairs",name:"军事-大頻道"},{slug:"ZhengZhi",name:"政治"},{slug:"WenHua",name:"文化"},{slug:"chanjing",name:"产经"},{slug:"qiche",name:"观出行"},{slug:"gongye-keji",name:"科技"},{slug:"ChengShi",name:"城事"},{slug:"GuanJinRong",name:"观金融"},{slug:"XinShiDai",name:"新时代"},{slug:"ChaoJiGongCheng",name:"超级工程"},{slug:"NengYuanZhanLue",name:"能源战略"},{slug:"RenGongZhiNeng",name:"人工智能"},{slug:"XinZhiGuanChaSuoNews",name:"心智观察所"},{slug:"YiLangJuShi",name:"伊朗局势"},{slug:"MeiGuoMeng",name:"美国一梦"},{slug:"MeiGuoJingJi",name:"美国经济"},{slug:"ELuoSiZhiSheng",name:"俄罗斯之声"},{slug:"lianganyuanzhuopai",name:"两岸圆桌派"},{slug:"ZheJiuShiZhongGuo",name:"这就是中国"},{slug:"YiZhouJunQingGuanCha",name:"一周军事观察"},{slug:"feizhoushangkou",name:"非洲之窗"},{slug:"toutiao",name:"观察者头条"},{slug:"gushi",name:"股市"},{slug:"guanwangwenyu",name:"新潮观鱼"},{slug:"jingtiriben",name:"冲破战后秩序 日本想干什么"},{slug:"DaoGuoDianAVI",name:"日本"}];function Me(t={}){let e=ot(t,"baseUrl");ut(e)||(e=_e),e=e.replace(/\/+$/,"");let r=ot(t,"maxRetries");r=Ut(r)?Lt(r):5;let n=ot(t,"timeout");n=Pt(n)?Lt(n):null;let a=ot(t,"showLog");mt(a)||(a=!0);let s={userAgent:ve,referer:e,maxRetries:r};null!==n&&(s.timeoutMs=n);let i=ot(t,"pageDelayMs");i=Ut(i)?Lt(i):1e3;let o=ot(t,"maxPages");return o=Pt(o)?Math.min(Lt(o),50):50,{baseUrl:e,showLog:a,pageDelayMs:i,maxPages:o,optFetch:s}}async function Ae(t,e){let r=await Se(t,e.optFetch);if("success"!==r.status){let e=new Error(r.message||"fetch failed");throw e.reason=r.reason,e.url=t,e.httpCode=r.httpCode,e}return r.html}function xe(t){let e=t.match(/<dt>[A-Z]<\/dt>/g);return!!e&&e.length>=5}function Te(t,e){let r,n=t.replace(/\n/g," "),a=[],s=new Set,i=/<a[^>]+href="\/([A-Za-z][a-zA-Z0-9_-]+)\/(\d{4}_\d{2}_\d{2}_\d+)\.shtml"(?:[^>]*title="([^"]+)")?[^>]*>([^<]*)<\/a>/g;for(;null!==(r=i.exec(n));){let t=r[1],n=r[2],i=r[3]&&Qt(r[3]).trim(),o=r[4]&&Qt(r[4]).replace(/<[^>]+>/g,"").trim(),l=i||o||"",u=`${t}/${n}`;!s.has(u)&&l&&(s.add(u),a.push({url:`${e}/${t}/${n}.shtml`,title:l,slug:t}))}return a}async function Ee(t,e){let r=[],n=new Set,a=0;for(let s=1;s<=e.maxPages;s++){let i=`${e.baseUrl}/${t}/list_${s}.shtml`;e.showLog&&process.stderr.write(`[info] fetching ${t} list_${s} ...\n`);let o=null;try{o=await Ae(i,e)}catch(t){if(1===s)throw t;e.showLog&&process.stderr.write(`[info] page ${s} fetch error (assumed end of list): ${t.message}\n`);break}if(xe(o)){if(1===s){let e=new Error(`slug "${t}" 不存在:請求 list 頁被觀察者網 302 導向首頁。`);throw e.reason="redirected-to-homepage",e}e.showLog&&process.stderr.write(`[info] page ${s} 被導向首頁,視為到底,停止翻頁\n`);break}a++;let l=Te(o,e.baseUrl).filter(t=>!n.has(t.url));if(0===l.length){e.showLog&&process.stderr.write(`[info] page ${s} 無新項目,停止翻頁\n`);break}for(let t of l)n.add(t.url);r.push(...l),s<e.maxPages&&await It(e.pageDelayMs)}return{items:r,pages_fetched:a}}async function Oe(t={}){let e=Me(t);return function(t){let e=t.replace(/\n/g," "),r=[],n=new Set,a=[...e.matchAll(/<dt>([A-Z])<\/dt>\s*<dd[^>]*>([\s\S]*?)<\/dd>/g)];for(let[,t,e]of a){let a,s=/<a[^>]+href="(?:\.\.\/|\/)?([A-Za-z][a-zA-Z0-9_-]+)\/list_1\.shtml"[^>]*>([^<]+)<\/a>/g;for(;null!==(a=s.exec(e));){let e=a[1],s=Qt(a[2]).trim();s&&!n.has(e)&&(n.add(e),r.push({slug:e,name:s,letter:t}))}}return r}(await Ae(`${e.baseUrl}/`,e))}function ke(t,e){return Array.isArray(t)&&e&&t.find(t=>t.name===e)||null}function je(t){return t&&De.find(e=>e.name===t)||null}let Ce={timeout:3e4,maxRetries:5,baseDelayMs:3e3,maxDelayMs:15e3,label:"fetch-hacker-news"};let Le={responseType:"text",timeout:3e4,maxRetries:10,baseDelayMs:5e3,maxDelayMs:3e4,retryStatus:[403],label:"fetch-moneydj"},Pe=/^(\d{2}\/\d{2}\s+\d{2}:\d{2}|\d{2}:\d{2}|昨\s*\d{2}:\d{2})$/;let Ue=5e3,Ie=3e4,Re=[{name:"上市",marketKind:"sii"},{name:"上櫃",marketKind:"otc"},{name:"興櫃",marketKind:"rotc"},{name:"公開發行",marketKind:"pub"}];async function Ye(t,e,r){let n=null;for(let a=1;a<=r.maxRetries+1;a++){if(n=await t.evaluate(async t=>{try{let e=await fetch(t.url,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t.payload)});if(e.status>=500||403===e.status||429===e.status)return{error:`HTTP ${e.status}`,retryable:!0};let r=await e.text();try{let t=JSON.parse(r),e=t&&t.code;return 200!==e&&406!==e?{error:`MOPS code ${e}: ${t&&t.message||""}`,json:t,raw:r.substring(0,500),retryable:!1}:{json:t,raw:r.substring(0,500)}}catch(t){return{error:"Parse Error",raw:r,retryable:!1}}}catch(t){return{error:t.toString(),retryable:!0}}},e),!n.error)return n;let s=!1!==n.retryable,i=r.maxRetries+1-a;if(!s||i<=0)return n;let o=Math.min(r.baseDelayMs*a,r.maxDelayMs);r.showLog&&console.warn(`[${e.name}][Retry ${a}/${r.maxRetries}] ${n.error} — 等待 ${o/1e3}s 後重試...`),await It(o)}return n}let Ne={responseType:"text",timeout:3e4,maxRetries:5,baseDelayMs:3e3,maxDelayMs:15e3,retryStatus:[404],label:"fetch-rss"};async function Fe(t,e){let r=await Se(t,{timeoutMs:e.timeout,maxRetries:e.maxRetries});if("success"!==r.status){let e=new Error(r.message||"curl fetch failed");throw e.statusCode=r.httpCode,e.reason=r.reason,e.url=t,e}return r.html}let He={responseType:"text",timeout:3e4,maxRetries:10,baseDelayMs:5e3,maxDelayMs:3e4,retryStatus:[403],label:"fetch-statementdog"},qe=".statementdog-news-list-item";function ze(t){if(!ut(t))return!1;if(!/^\d{8}$/.test(t))return!1;let e=Lt(t.slice(0,4)),r=Lt(t.slice(4,6)),n=Lt(t.slice(6,8)),a=new Date(e,r-1,n);return a.getFullYear()===e&&a.getMonth()===r-1&&a.getDate()===n}let We={responseType:"text",encoding:"big5",timeout:15e3,maxRetries:10,baseDelayMs:5e3,maxDelayMs:3e4,label:"fetch-taifex"},Be={"外資及陸資":"foreign","外資":"foreign","投信":"trust","自營商":"dealers"};function Ke(t){let e=[],r="",n=!1;for(let a=0;a<t.length;a++){let s=t[a];n?'"'===s?'"'===t[a+1]?(r+='"',a++):n=!1:r+=s:","===s?(e.push(r.trim()),r=""):'"'===s&&0===r.length?n=!0:r+=s}return e.push(r.trim()),e}function Ge(t){let e=t.trim().split("\n").map(t=>t.trim()).filter(t=>t.length>0);if(e.length<2)return[];let r=Ke(e[0]),n=[];for(let t=1;t<e.length;t++){let a=Ke(e[t]),s={};for(let t=0;t<r.length;t++)s[r[t]]=a[t]||"";n.push(s)}return n}function Xe(t){if(!t||"-"===t||""===t)return null;let e=Number(t.replace(/,/g,""));return isNaN(e)?null:e}function Ze(t){if(!ut(t))return"";return`${parseInt(t.substring(0,4),10)-1911}/${t.substring(4,6)}/${t.substring(6,8)}`}let Je={timeout:15e3,maxRetries:10,baseDelayMs:5e3,maxDelayMs:3e4,label:"fetch-tpex-3insti"},Ve=["代號","名稱","外陸資買進股數(不含外資自營商)","外陸資賣出股數(不含外資自營商)","外陸資買賣超股數(不含外資自營商)","外資自營商買進股數","外資自營商賣出股數","外資自營商買賣超股數","外資及陸資買進股數","外資及陸資賣出股數","外資及陸資買賣超股數","投信買進股數","投信賣出股數","投信買賣超股數","自營商買進股數(自行買賣)","自營商賣出股數(自行買賣)","自營商買賣超股數(自行買賣)","自營商買進股數(避險)","自營商賣出股數(避險)","自營商買賣超股數(避險)","自營商買進股數","自營商賣出股數","自營商買賣超股數","三大法人買賣超股數合計"];function Qe(t){return"string"!=typeof t?t:parseInt(t.replace(/,/g,""),10)||0}let tr={timeout:15e3,maxRetries:10,baseDelayMs:5e3,maxDelayMs:3e4,label:"fetch-tpex-margin"};let er={timeout:15e3,maxRetries:10,baseDelayMs:5e3,maxDelayMs:3e4,label:"fetch-tpex-stock"};let rr={responseType:"text",timeout:3e4,maxRetries:10,baseDelayMs:5e3,maxDelayMs:3e4,label:"fetch-tw-data-holiday"};let nr={timeout:15e3,maxRetries:10,baseDelayMs:5e3,maxDelayMs:3e4,label:"fetch-twse-margin"};let ar={timeout:1e4,maxRetries:10,baseDelayMs:5e3,maxDelayMs:3e4,label:"fetch-twse-stock"};let sr={timeout:15e3,maxRetries:10,baseDelayMs:5e3,maxDelayMs:3e4,label:"fetch-twse-t86"};let ir={fetchRSS:async function(t,e={}){if(!ut(t)||!/^https?:\/\//i.test(t))throw new Error("rssUrl 須為有效的 http/https RSS 網址");let r=ot(e,"method");"curl"!==r&&"auto"!==r&&(r="fetch");let n=ot(e,"withContent");mt(n)||(n=!1);let s=await async function(t,e,r){if("curl"===e)return await Fe(t,r);if("auto"===e)try{return await Fe(t,r)}catch(e){return await Ft(t,r)}return await Ft(t,r)}(t,r,qt(e,Ne)),i=new a,o=await i.parseString(s),l=String(ot(o,"title","")||"").trim(),u=ot(o,"items");return dt(u)||(u=[]),u.map(t=>{let e={url:String(ot(t,"link","")||"").trim(),time:Zt(ot(t,"isoDate","")||ot(t,"pubDate","")),title:String(ot(t,"title","")||"").trim(),description:String(ot(t,"contentSnippet","")||ot(t,"summary","")||"").trim(),from:String(ot(t,"creator","")||l).trim()};return n&&(e.content=function(t){if(!lt(t))return"";let e=t;return e=e.replace(/<script[\s\S]*?<\/script>/gi,""),e=e.replace(/<style[\s\S]*?<\/style>/gi,""),e=e.replace(/<\/(?:p|div|li|h[1-6])>/gi,"\n"),e=e.replace(/<br\s*\/?>/gi,"\n"),e=e.replace(/<[^>]+>/g,""),e=Qt(e),e=e.replace(/\u00A0/g," "),e=e.split("\n").map(t=>t.replace(/[ \t]+/g," ").trim()).join("\n"),e=e.replace(/\n{3,}/g,"\n\n"),e.trim()}(ot(t,"content:encoded","")||ot(t,"content","")||ot(t,"summary","")||ot(t,"description",""))),e})},fetchHackerNews:async function(t=30,e={}){t=Pt(t)?Lt(t):30;let r=ot(e,"apiBase");ut(r)||(r="https://hacker-news.firebaseio.com/v0"),r=r.replace(/\/+$/,"");let n=qt(e,Ce),a=await Ft(`${r}/newstories.json`,n);dt(a)||(a=[]);let s=a.slice(0,t),i=[];for(let t=0;t<s.length;t+=10){let e=s.slice(t,t+10),a=await Promise.allSettled(e.map(t=>Ft(`${r}/item/${t}.json`,n)));for(let t of a)"fulfilled"===t.status&&i.push(t.value)}return i.filter(t=>t&&"story"===t.type).map(t=>({url:String(ot(t,"url","")||`https://news.ycombinator.com/item?id=${ot(t,"id","")}`).trim(),time:Zt(ot(t,"time",0)),title:String(ot(t,"title","")||"").trim(),description:"",from:"Hacker News"}))},fetchAiNewsAggregator:async function(t={}){let e=ot(t,"url");ut(e)||(e="https://raw.githubusercontent.com/SuYxh/ai-news-aggregator/refs/heads/main/data/latest-24h.json");let r=ot(await Ft(e,qt(t,Jt)),"items");return dt(r)||(r=[]),r.map(t=>({url:String(ot(t,"url","")||"").trim(),time:Zt(ot(t,"published_at","")),title:String(ot(t,"title","")||"").trim(),description:"",from:String(ot(t,"source","")||"").trim()}))},fetchCnyes:async function(t={}){let e=ot(t,"url");ut(e)||(e="https://api.cnyes.com/media/api/v1/newslist/category/tw_stock");let r=ot(t,"targetTotal");r=Pt(r)?Lt(r):100;let n=ot(t,"pageLimit");n=Pt(n)?Lt(n):30;let a=ot(t,"daysBack");a=Pt(a)?Lt(a):10;let s=ot(t,"pageDelayMs");s=Ut(s)?Lt(s):500;let i=qt(t,pe),o=i.showLog,l=Math.floor(Date.now()/1e3),u=l-86400*a;o&&console.log("Starting to fetch Anue (tw_stock) news...");let c=[],h=1;for(;c.length<r;){let t=new URLSearchParams({page:String(h),limit:String(n),isCategoryHeadline:"1",startAt:String(u),endAt:String(l)}),r=ot(await Ft(`${e}?${t.toString()}`,i),"items.data");if(!dt(r)){o&&console.log("No more items found.");break}c=c.concat(r),o&&console.log(`Page ${h}: Fetched ${r.length} items. Total so far: ${c.length}`),h++,await It(s)}let f=c.slice(0,r);return o&&console.log(`Total items collected: ${f.length}`),f.map(t=>{let e=Zt(ot(t,"publishAt",0));return""===e&&o&&console.warn(`[fetch-cnyes] 時間格式化失敗(newsId=${ot(t,"newsId","")}, publishAt=${ot(t,"publishAt","")}) — 該筆time退回空字串`),{time:e,title:ot(t,"title",""),link:`https://news.cnyes.com/news/id/${ot(t,"newsId","")}`}})},fetchMoneydj:async function(t={}){let e=ot(t,"baseUrl");ut(e)||(e="https://www.moneydj.com/kmdj/news/newsreallist.aspx?a=mb06&index1=");let r=ot(t,"totalPages");r=Pt(r)?Lt(r):50;let n=ot(t,"onPageDone");(function(t){let e=Object.prototype.toString.call(t);return"[object Function]"===e||"[object AsyncFunction]"===e})(n)||(n=()=>{});let a=qt(t,Le),s=a.showLog,o=ot(t,"pageDelayMs");o=Pt(o)||0===o?Lt(o):null;let l=new URL(e).origin,u=async t=>{let r=await Ft(`${e}${t}`,{...a,label:`${Le.label} Page ${t}`}),n=i.load(r),s=[];return n("tr").each((t,e)=>{let r=n(e),a=r.find("td").eq(0).text().trim(),i=r.find("td").eq(1).find("a");if(a&&Pe.test(a)&&i.length>0){let t=i.attr("title")||i.text().trim(),e=i.attr("href");if(e){let r=e.startsWith("http")?e:l+e;s.push({time:a,title:t,link:r})}}}),s},c=[];for(let t=1;t<=r;t++){let e=null;try{e=await u(t)}catch(e){s&&console.warn(`[Page ${t}] 抓取失敗,已跳過:${e.message}`);continue}c=c.concat(e),n(t,e.length,r),t<r&&await It(null===o?Math.floor(2e3*Math.random())+1e3:o)}if(0===c.length)throw new Error("抓取到 0 筆新聞,可能是頁面結構改變或 selector 失效,請確認 MoneyDJ 頁面是否正常。");return c},fetchStatementdog:async function(t={}){let e=ot(t,"url");ut(e)||(e="https://statementdog.com/news/latest");let r=qt(t,He),n=r.showLog;n&&console.log(`Fetching ${e}...`);let a=await Ft(e,r),s=new URL(e).origin,o=i.load(a),l=o(qe).length>0,u=l?qe:'article, .news-item, [class*="news"][class*="item"]',c=l?".statementdog-news-list-item-title":'h2, h3, [class*="title"]',h=l?".statementdog-news-list-item-link":"a[href]",f=l?".statementdog-news-list-item-date":'time, [class*="date"], [class*="time"]';!l&&n&&console.warn("主要 CSS selector 未匹配,嘗試 fallback selector...");let g=[];if(o(u).each((t,e)=>{let r=o(e).find(c),n=l?o(e).find(h):o(e).find(h).first(),a=o(e).find(f),i=r.text().trim(),u=n.attr("href"),d=a.text().trim();i&&u&&(u.startsWith("http")||(u=`${s}${u.startsWith("/")?"":"/"}${u}`),g.push({time:d,title:i,link:u}))}),n&&console.log(`Extracted News Items: ${g.length}`),0===g.length)throw new Error("抓取到 0 筆新聞,可能是頁面結構改變或 selector 失效,請確認財報狗頁面是否正常。");return g},fetchMops:async function(t={}){let e=ot(t,"pageUrl");ut(e)||(e="https://mops.twse.com.tw/mops/#/web/t146sb10");let r=ot(t,"apiUrl");ut(r)||(r="https://mops.twse.com.tw/mops/api/t146sb10");let a=ot(t,"maxRetries");a=Ut(a)?Lt(a):10;let s=ot(t,"showLog");mt(s)||(s=!0);let i={maxRetries:a,baseDelayMs:Ue,maxDelayMs:Ie,showLog:s},o=Re.map(t=>{return{name:t.name,marketKind:t.marketKind,url:r,payload:(e=t.marketKind,{scopeType:"2",companyId:"",dateType:"2",firstDate:"",lastDate:"",marketKind:e,announcementBasis:"0",dateRangeType:"1",announcementType:"1",sort:"1",encodeURIComponent:1,step:1,firstin:1,off:1})};var e});s&&console.log("啟動瀏覽器...");let l=null;for(let t=1;t<=a+1;t++)try{l=await n.chromium.launch({headless:!0,executablePath:process.env.CHROME_PATH||void 0,channel:"chrome",args:["--no-sandbox","--disable-setuid-sandbox"],timeout:36e4});break}catch(e){if(a+1-t<=0)throw new Error(`瀏覽器啟動失敗(已重試 ${a} 次): ${e.message}`);let r=Math.min(Ue*t,Ie);s&&console.warn(`[browser.launch][Retry ${t}/${a}] ${e.message} — 等待 ${r/1e3}s 後重試...`),await It(r)}try{let t=await l.newPage();s&&console.log("前往 MOPS 重大訊息頁面 (t146sb10)...");for(let r=1;r<=a+1;r++)try{await t.goto(e,{waitUntil:"networkidle",timeout:6e4});break}catch(t){if(a+1-r<=0)throw t;let e=Math.min(Ue*r,Ie);s&&console.warn(`[page.goto][Retry ${r}/${a}] ${t.message} — 等待 ${e/1e3}s 後重試...`),await It(e)}await t.waitForTimeout(2e3);let r=[];for(let e of o){s&&console.log(`正在抓取 [${e.name}] 資料...`);let n=await Ye(t,e,i);r.push({market:e.name,marketKind:e.marketKind,data:n.json||n,...n.error&&{error:n.error},timestamp:(new Date).toISOString()}),await t.waitForTimeout(1e3)}if(s){let t=r.map(t=>{let e=ot(t,"data.result",ot(t,"data")),r=Array.isArray(e)?e.length:0;return`${t.market}: 取得 ${r} 筆資料`});console.log("抓取完成。摘要:",t)}let n=r.some(t=>t.error);return{results:r,hasError:n}}finally{await l.close()}},fetchTwseStock:async function(t,e,r={}){if(!ze(t))throw new Error(`dateStr 須為合法之 YYYYMMDD 字串,得到: ${t}`);let n=ot(r,"baseUrl");ut(n)||(n="https://www.twse.com.tw"),n=n.replace(/\/+$/,"");let a=qt(r,ar),s=a.showLog,i=ut(e)&&"all"!==e.toLowerCase(),o=i?e:"ALLBUT0999",l="";l=i?`${n}/exchangeReport/STOCK_DAY?response=json&date=${t}&stockNo=${o}`:`${n}/exchangeReport/MI_INDEX?response=json&date=${t}&type=ALLBUT0999`,s&&(console.log(`Fetching TWSE data: ${t}, Stock: ${o}`),console.log(`URL: ${l}`));let u=await Ft(l,a);if("OK"!==ot(u,"stat"))throw new Error(`TWSE API returned: ${ot(u,"stat")}`);if(i&&Array.isArray(u.data)){let r=Ze(t),n=u.data.filter(t=>t[0]===r);if(u.data=n,0===n.length)throw new Error(`TWSE 個股 ${e} 於 ${t} 無交易資料(可能為假日或停盤)`)}return u},fetchTpexStock:async function(t,e,r={}){if(!ze(t))throw new Error(`dateStr 須為合法之 YYYYMMDD 字串,得到: ${t}`);let n=ot(r,"baseUrl");ut(n)||(n="https://www.tpex.org.tw"),n=n.replace(/\/+$/,"");let a=qt(r,er),s=a.showLog,i=dt(e)?e:[],o=Ze(t),l=`${n}/web/stock/aftertrading/daily_close_quotes/stk_quote_result.php?l=zh-tw&d=${o}&s=0,asc,0&o=json`;s&&(console.log(`Fetching TPEX data: ${t} (${o})`),console.log(`Target: ${i.length>0?i.join(", "):"All Market"}`),console.log(`URL: ${l}`));let u=await Ft(l,a),c=Array.isArray(u.tables)?u.tables:[],h=c.find(t=>ot(t,"title","").includes("行情")&&ot(t,"data.length",0)>0)||c.find(t=>ot(t,"data.length",0)>0),f=ot(h,"data");if(!dt(f))throw new Error("TPEX API returned no data. Possibly a holiday or data not yet available.");if(!Array.isArray(f[0])||f[0].length<8)throw new Error(`TPEX 行情資料欄數不符預期(首列 ${Array.isArray(f[0])?f[0].length:"N/A"} 欄,應 >= 8),可能 API 格式變更`);let g=f;if(i.length>0&&(g=g.filter(t=>i.includes(t[0])),0===g.length))throw new Error(`指定個股 ${i.join(",")} 在 ${t} 之上櫃資料中查無資料(可能為上市股、代碼有誤、或當日無交易)`);return{source:"tpex",date:t,count:g.length,data:g}},fetchTwseMargin:async function(t,e,r={}){if(!ut(t)||!/^\d{8}$/.test(t))throw new Error(`日期參數無效:格式須為 YYYYMMDD (收到 "${t}")`);if(!ze(t))throw new Error(`日期參數無效:不合法的日期 (${t})`);let n=ot(r,"baseUrl");ut(n)||(n="https://www.twse.com.tw"),n=n.replace(/\/+$/,"");let a=qt(r,nr),s=a.showLog,i=dt(e)?e.filter(Boolean):[],o=`${n}/rwd/zh/marginTrading/MI_MARGN?date=${t}&selectType=ALL&response=json`;s&&(console.log(`Fetching TWSE margin data: ${t}`),console.log(`Target: ${i.length>0?i.join(", "):"All Market"}`),console.log(`URL: ${o}`));let l=await Ft(o,a);if("OK"!==ot(l,"stat"))throw new Error(`TWSE MI_MARGN API returned: ${ot(l,"stat")}`);let u=Array.isArray(l.tables)?l.tables:[],c=u.find(t=>ot(t,"data.length",0)>0&&ot(t,"title","").includes("融資融券彙總"));if(c||(c=u.find(t=>ot(t,"data.length",0)>0&&Array.isArray(t.fields)&&t.fields.some(t=>String(t).includes("融資"))&&t.fields.some(t=>String(t).includes("融券")))),!c||!dt(ot(c,"data")))throw new Error("TWSE MI_MARGN: 找不到融資融券彙總資料表");if(!Array.isArray(c.fields)||c.fields.length<16)throw new Error(`TWSE 融資融券資料欄數不符預期(fields ${ot(c,"fields.length","N/A")} 欄,應 >= 16),可能 API 格式變更`);let h=c.data;if(i.length>0&&(h=h.filter(t=>i.includes(String(t[0]||"").trim())),0===h.length))throw new Error(`指定個股 ${i.join(",")} 不在上市融資融券資料中(可能為上櫃股或代碼有誤)`);let f=h.map(t=>{let e=Qe(t[2]),r=Qe(t[3]),n=Qe(t[6]),a=Qe(t[5]),s=Qe(t[8]),i=Qe(t[9]),o=Qe(t[12]),l=Qe(t[11]);return{code:String(t[0]||"").trim(),name:String(t[1]||"").trim(),marginBuy:e,marginSell:r,marginCashRepay:Qe(t[4]),marginPrevBalance:a,marginBalance:n,marginChange:n-a,marginLimit:Qe(t[7]),shortSell:i,shortBuy:s,shortCashRepay:Qe(t[10]),shortPrevBalance:l,shortBalance:o,shortChange:o-l,shortLimit:Qe(t[13]),offset:Qe(t[14]),note:String(t[15]||"").trim()}});return s&&console.log(`Fetched ${f.length} records.`),{source:"twse_margin",date:t,count:f.length,data:f}},fetchTpexMargin:async function(t,e,r={}){if(!ut(t)||!/^\d{8}$/.test(t))throw new Error(`日期參數無效:格式須為 YYYYMMDD (收到 "${t}")`);if(!ze(t))throw new Error(`日期參數無效:不合法的日期 (${t})`);let n=ot(r,"baseUrl");ut(n)||(n="https://www.tpex.org.tw"),n=n.replace(/\/+$/,"");let a=qt(r,tr),s=a.showLog,i=dt(e)?e.filter(Boolean):[],o=Ze(t),l=`${n}/web/stock/margin_trading/margin_balance/margin_bal_result.php?l=zh-tw&d=${o}&o=json`;s&&(console.log(`Fetching TPEX margin data: ${t} (${o})`),console.log(`Target: ${i.length>0?i.join(", "):"All Market"}`),console.log(`URL: ${l}`));let u=await Ft(l,a),c=Array.isArray(u.tables)?u.tables:[],h=c.find(t=>ot(t,"data.length",0)>0&&Array.isArray(t.fields)&&t.fields.some(t=>String(t).includes("資餘額"))&&t.fields.some(t=>String(t).includes("券餘額")))||c.find(t=>ot(t,"data.length",0)>0);if(!h||!dt(ot(h,"data")))throw new Error("TPEX margin API returned no data. Possibly a holiday or data not yet available.");let f=Array.isArray(h.fields)?h.fields:[];if(!String(f[6]||"").includes("資餘額")||!String(f[14]||"").includes("券餘額"))throw new Error(`TPEX 融資融券資料欄位佈局與預期不符(index6 應含「資餘額」實為「${f[6]??""}」、index14 應含「券餘額」實為「${f[14]??""}」);可能 API 格式變更,停止解析以免產生錯誤資料`);let g=h.data;if(i.length>0&&(g=g.filter(t=>i.includes(String(t[0]||"").trim())),0===g.length))throw new Error(`指定個股 ${i.join(",")} 不在上櫃融資融券資料中(可能為上市股或代碼有誤)`);let d=g.map(t=>{let e=Qe(t[2]),r=Qe(t[3]),n=Qe(t[4]),a=Qe(t[6]),s=Qe(t[10]),i=Qe(t[11]),o=Qe(t[12]),l=Qe(t[14]);return{code:String(t[0]||"").trim(),name:String(t[1]||"").trim(),marginBuy:r,marginSell:n,marginCashRepay:Qe(t[5]),marginPrevBalance:e,marginBalance:a,marginChange:a-e,marginLimit:Qe(t[9]),shortSell:i,shortBuy:o,shortCashRepay:Qe(t[13]),shortPrevBalance:s,shortBalance:l,shortChange:l-s,shortLimit:Qe(t[17]),offset:Qe(t[18]),note:String(t[19]||"").trim()}});return s&&console.log(`Fetched ${d.length} records.`),{source:"tpex_margin",date:t,count:d.length,data:d}},fetchTwseT86:async function(t,e,r={}){if(!ut(t)||!/^\d{8}$/.test(t))throw new Error(`dateStr must be YYYYMMDD, got: ${t}`);if(!ze(t))throw new Error(`dateStr 不是合法日期: ${t}`);let n=ot(r,"baseUrl");ut(n)||(n="https://www.twse.com.tw"),n=n.replace(/\/+$/,"");let a=qt(r,sr),s=a.showLog,i=dt(e)?e:[],o=`${n}/rwd/zh/fund/T86?response=json&date=${t}&selectType=ALL`;s&&(console.log(`Fetching from: ${o}`),console.log(`Target: ${0===i.length?"All Market":i.join(", ")}`));let l=await Ft(o,a);if("OK"!==ot(l,"stat"))throw new Error(`TWSE T86 API returned: ${ot(l,"stat")}`);let u=ot(l,"fields"),c=ot(l,"data");if(!Array.isArray(c))throw new Error("TWSE T86: data not found in response.");if(!Array.isArray(u))throw new Error("TWSE T86: fields not found in response.");let h=c.map(t=>{let e={};return u.forEach((r,n)=>{let a=t[n];"string"==typeof a&&(a=a.trim()),e[r]=a}),e});if(i.length>0){let t=u.find(t=>String(t).includes("證券代號"));if(!t)throw new Error("無法篩選個股:API 回應中找不到證券代號欄位");h=h.filter(e=>i.includes(e[t]))}return s&&console.log(`Fetched ${h.length} records.`),{source:"twse",date:t,data:h}},fetchTpex3insti:async function(t,e,r={}){if(!ut(t)||!/^\d{8}$/.test(t))throw new Error(`dateStr must be YYYYMMDD, got: ${t}`);if(!ze(t))throw new Error(`dateStr 不是合法日期: ${t}`);let n=ot(r,"baseUrl");ut(n)||(n="https://www.tpex.org.tw"),n=n.replace(/\/+$/,"");let a=qt(r,Je),s=a.showLog,i=dt(e)?e:[],o=`${n}/web/stock/3insti/daily_trade/3itrade_hedge_result.php?l=zh-tw&t=D&d=${Ze(t)}&o=json`;s&&(console.log(`Fetching from: ${o}`),console.log(`Target: ${0===i.length?"All Market":i.join(", ")}`));let l=await Ft(o,a);if(!dt(ot(l,"tables")))throw new Error("TPEX 3insti: tables not found in response. Possibly a holiday or no data.");let u=l.tables,c=u.find(t=>Array.isArray(t.fields)&&t.fields.some(t=>String(t).includes("代號"))&&t.fields.some(t=>String(t).includes("名稱")))||u[0],h=ot(c,"fields"),f=ot(c,"data");if(!Array.isArray(h)||!Array.isArray(f))throw new Error("TPEX 3insti: data/fields not found in table.");!function(t){if(t.length!==Ve.length)throw new Error(`TPEX 3insti: 欄數異常,預期 ${Ve.length} 得 ${t.length}(疑似 API 改版,請重新校準 TPEX_FIELD_MAP)`);if(!String(t[0]).includes("代號")||!String(t[1]).includes("名稱"))throw new Error(`TPEX 3insti: 前兩欄非「代號/名稱」(得「${t[0]}」「${t[1]}」,疑似 API 改版)`);if(!String(t[t.length-1]).includes("合計"))throw new Error(`TPEX 3insti: 末欄非「合計」(得「${t[t.length-1]}」,疑似 API 改版)`);let e=["買進股數","賣出股數","買賣超股數"];for(let r=2;r<t.length-1;r++){let n=e[(r-2)%3];if(String(t[r])!==n)throw new Error(`TPEX 3insti: 第 ${r} 欄預期「${n}」得「${t[r]}」(疑似 API 改版,欄序已變)`)}}(h);let g=f.map(t=>{let e={};return Ve.forEach((r,n)=>{let a=t[n];"string"==typeof a&&(a=a.trim()),e[r]=a}),e}).filter(t=>0===i.length||i.includes(t["代號"]));return s&&console.log(`Fetched ${g.length} records.`),{source:"tpex",date:t,data:g}},fetchTaifex:async function(t,e={}){if(!ut(t)||!/^\d{8}$/.test(t))throw new Error(`dateStr 須為 YYYYMMDD 字串,得到: ${t}`);if(!ze(t))throw new Error(`dateStr 非合法日期: ${t}`);let r=ot(e,"baseUrl");ut(r)||(r="https://www.taifex.com.tw"),r=r.replace(/\/+$/,"");let n=qt(e,We),a=n.showLog,s={baseUrl:r,showLog:a,optFetch:n},i=ot(e,"interRequestDelayMs");i=Ut(i)?Lt(i):1e3;let o=`${t.substring(0,4)}/${t.substring(4,6)}/${t.substring(6,8)}`;a&&console.log(`Fetching TAIFEX data for ${t} (${o})`);let l=[],u=null,c=null,h=null;try{u=await async function(t,e){let r=`${e.baseUrl}/cht/3/futDataDown?down_type=1&queryStartDate=${t}&queryEndDate=${t}&commodity_id=TX`;e.showLog&&console.log(`Fetching futures data: ${r}`);let n=Ge(await Ft(r,{...e.optFetch,label:`${We.label} Futures`}));if(0===n.length)throw new Error("台指期行情:無資料(可能非交易日)");let a=n.filter(t=>"TX"===t["契約"]&&!t["到期月份(週別)"].includes("/"));if(0===a.length)throw new Error("台指期行情:找不到 TX 合約資料");a.sort((t,e)=>t["到期月份(週別)"].trim().localeCompare(e["到期月份(週別)"].trim()));let s=a[0]["到期月份(週別)"].trim(),i=a.filter(t=>t["到期月份(週別)"].trim()===s),o=i.find(t=>"一般"===t["交易時段"]),l=i.find(t=>"盤後"===t["交易時段"]),u={contractMonth:s,open:null,high:null,low:null,close:null,settlement:null,volume:null,afterHoursClose:null,afterHoursSettlement:null,afterHoursVolume:null};return o&&(u.open=Xe(o["開盤價"]),u.high=Xe(o["最高價"]),u.low=Xe(o["最低價"]),u.close=Xe(o["收盤價"]),u.settlement=Xe(o["結算價"]),u.volume=Xe(o["成交量"])),l&&(u.afterHoursClose=Xe(l["收盤價"]),u.afterHoursSettlement=Xe(l["結算價"]),u.afterHoursVolume=Xe(l["成交量"])),e.showLog&&(console.log(` 台指期近月 (${s}): 開${u.open} 高${u.high} 低${u.low} 收${u.close} 結算${u.settlement} 量${u.volume}`),null!==u.afterHoursClose&&console.log(` 盤後: 收${u.afterHoursClose} 結算${u.afterHoursSettlement} 量${u.afterHoursVolume}`)),u}(o,s)}catch(t){let e=`台指期行情: ${ot(t,"message",t)}`;a&&console.error(e),l.push(e)}await It(i);try{c=await async function(t,e){let r=`${e.baseUrl}/cht/3/futContractsDateDown?queryStartDate=${t}&queryEndDate=${t}&commodityId=TXF`;e.showLog&&console.log(`Fetching institutional data: ${r}`);let n=Ge(await Ft(r,{...e.optFetch,label:`${We.label} Institutional`}));if(0===n.length)throw new Error("三大法人期貨未平倉:無資料(可能非交易日)");let a={};for(let t of n){let r=t["身份別"],n=Be[r];n&&(a[n]={longContracts:Xe(t["多方未平倉口數"]),longAmount:Xe(t["多方未平倉契約金額(千元)"]),shortContracts:Xe(t["空方未平倉口數"]),shortAmount:Xe(t["空方未平倉契約金額(千元)"]),netContracts:Xe(t["多空未平倉口數淨額"]),netAmount:Xe(t["多空未平倉契約金額淨額(千元)"]),tradingLong:Xe(t["多方交易口數"]),tradingShort:Xe(t["空方交易口數"]),tradingNet:Xe(t["多空交易口數淨額"])},e.showLog&&console.log(` ${r}: 未平倉淨額 ${a[n].netContracts} 口`))}if(0===Object.keys(a).length)throw new Error("三大法人期貨未平倉:無法解析身份別(可能官方變更欄位用語)");return a}(o,s)}catch(t){let e=`三大法人: ${ot(t,"message",t)}`;a&&console.error(e),l.push(e)}await It(i);try{h=await async function(t,e){let r=`${e.baseUrl}/cht/3/pcRatioDown?queryStartDate=${t}&queryEndDate=${t}`;e.showLog&&console.log(`Fetching P/C ratio: ${r}`);let n=Ge(await Ft(r,{...e.optFetch,label:`${We.label} PCRatio`}));if(0===n.length)throw new Error("Put/Call Ratio:無資料(可能非交易日)");let a=n[0],s={putVolume:Xe(a["賣權成交量"]),callVolume:Xe(a["買權成交量"]),ratio:Xe(a["買賣權成交量比率%"]),putOpenInterest:Xe(a["賣權未平倉量"]),callOpenInterest:Xe(a["買權未平倉量"]),openInterestRatio:Xe(a["買賣權未平倉量比率%"])};return e.showLog&&console.log(` Put ${s.putVolume} / Call ${s.callVolume} = ${s.ratio}%`),s}(o,s)}catch(t){let e=`Put/Call Ratio: ${ot(t,"message",t)}`;a&&console.error(e),l.push(e)}if(!(u||c||h)){let t=new Error(`所有資料抓取失敗: ${l.join("; ")}`);throw t.errors=l,t}return{date:t,futures:u?{tx:u}:null,institutional:c||null,pcRatio:h||null,errors:l}},fetchTwDataHoliday:async function(t,e={}){let r=ot(e,"url");ut(r)||(r="https://openapi.twse.com.tw/v1/holidaySchedule/holidaySchedule");let n=qt(e,rr),a=await Ft(r,n),s=null;try{s=JSON.parse(a)}catch(t){throw new Error("API 回傳非 JSON 格式(可能為維護頁面或網路中介),請稍後再試")}if(!dt(s))throw new Error("API 回傳空陣列或格式異常");let i=s.filter(t=>!function(t){let e=String(ot(t,"Name","")),r=String(ot(t,"Description",""));return/交易日/.test(e)||/市場無交易/.test(e)||/開始交易/.test(r)||/最後交易/.test(r)}(t)).map(t=>{return{date:(e=ot(t,"Date",""),`${parseInt(e.substring(0,e.length-4),10)+1911}${e.substring(e.length-4)}`),rocDate:ot(t,"Date",""),name:ot(t,"Name",""),weekday:ot(t,"Weekday",""),description:String(ot(t,"Description","")||"").replace(/<br\s*\/?>/gi,"").trim()};var e}),o=new Set,l=i.filter(t=>!o.has(t.date)&&(o.add(t.date),!0));l.sort((t,e)=>t.date.localeCompare(e.date));let u={dataYear:l.length>0?l[0].date.substring(0,4):null,totalHolidays:l.length,holidays:l};if(ut(t)&&/^\d{8}$/.test(t)){u.checkDate=t;let e=l.find(e=>e.date===t);u.isHoliday=!!e,u.holidayName=e?e.name:null}return u},fetchAisixiang:me,fetchGuancha:{BASE_URL:_e,USER_AGENT:ve,MAX_PAGES:50,KNOWN_TOPICS:De,safeFilename:re,fetchAuthorsList:Oe,lookupAuthor:ke,lookupTopic:je,fetchAuthorArticles:async function(t={}){let e=Me(t),r=ot(t,"name");ut(r)||(r="");let n=ot(t,"slug");if(ut(n)||(n=""),!r&&!n)throw new Error("需要 name 或 slug");let a=n,s=r;if(!a){e.showLog&&process.stderr.write("[info] fetching authors index from / ...\n");let n=await Oe(t),i=ke(n,r);if(!i)return{status:"success",site:"guancha",mode:"author",query:r,fetched_at:(new Date).toISOString(),authors_count:n.length,count:0,items:[],message:`"${r}" 不在觀察者網作者索引中(共 ${n.length} 位)。尚無此作者文章。提醒:本函數不轉繁簡,呼叫端負責用站方登錄字形(簡體)。`};a=i.slug,s=i.name}let i=`${e.baseUrl}/${a}`,o=null;try{o=await Ee(a,e)}catch(t){return{status:"error",site:"guancha",mode:"author",query:s||a,resolved:{slug:a,url:i,name:s},fetched_at:(new Date).toISOString(),reason:t.reason,error:t.message}}return{status:"success",site:"guancha",mode:"author",query:s||a,resolved:{slug:a,url:i,name:s,pages_fetched:o.pages_fetched},fetched_at:(new Date).toISOString(),count:o.items.length,items:o.items}},fetchKeywordArticles:async function(t,e={}){if(!ut(t))throw new Error("需要 keyword");return{status:"error",site:"guancha",mode:"keyword",query:t,fetched_at:(new Date).toISOString(),error:"unsupported-by-curl",message:"觀察者網搜尋 API(s.guancha.cn/main/search-v2)由 sojson.v4 混淆並走 MD5 簽名,本函數(純 curl 路徑)無法支援。如已知作者拼音 slug,請改用 fetchAuthorArticles({ slug });如已知主題 slug,請改用 fetchTopicArticles({ slug })。"}},fetchTitleArticles:async function(t,e={}){if(!ut(t))throw new Error("需要 keyword");return{status:"error",site:"guancha",mode:"title",query:t,fetched_at:(new Date).toISOString(),error:"unsupported-by-curl",message:"觀察者網無分「標題」與「全文」搜尋(兩者同源),搜尋 API 由 sojson.v4 混淆並走 MD5 簽名,本函數(純 curl 路徑)無法支援。如已知作者拼音 slug,請改用 fetchAuthorArticles({ slug })。"}},fetchTopicArticles:async function(t={}){let e=Me(t),r=ot(t,"name");ut(r)||(r="");let n=ot(t,"slug");if(ut(n)||(n=""),!r&&!n)throw new Error("需要 name 或 slug");let a=n,s=r;if(!a){let t=je(r);if(!t)return{status:"error",site:"guancha",mode:"topic",query:r,fetched_at:(new Date).toISOString(),topics_count:De.length,error:"topic-not-in-table",message:`主題 "${r}" 不在已知主題對照表中(共 ${De.length} 個)。觀察者網無公開主題清單頁,本函數採手工對照。建議直接傳 slug(拼音 slug)。本函數不自動轉向,請呼叫端決定是否重試。`};a=t.slug,s=t.name}let i=`${e.baseUrl}/${a}`,o=null;try{o=await Ee(a,e)}catch(t){return{status:"error",site:"guancha",mode:"topic",query:s||a,resolved:{slug:a,url:i,name:s},fetched_at:(new Date).toISOString(),reason:t.reason,error:t.message}}return{status:"success",site:"guancha",mode:"topic",query:s||a,resolved:{slug:a,url:i,name:s,pages_fetched:o.pages_fetched},fetched_at:(new Date).toISOString(),count:o.items.length,items:o.items}},fetchArticle:async function(t={}){let e=Me(t),r=ot(t,"url");if(!ut(r))throw new Error("需要 url");let n=null;try{n=await Ae(r,e)}catch(t){return{status:"error",site:"guancha",mode:"fetch",url:r,fetched_at:(new Date).toISOString(),error:t.message||"fetch failed"}}let a=function(t){let e=t.match(/<title>([\s\S]*?)<\/title>/i);return e?Qt(e[1].trim()):null}(n)||"",s=ee(n,"content all-txt");if("观察者网"===a||"觀察者網"===a||!s)return{status:"error",site:"guancha",mode:"fetch",url:r,fetched_at:(new Date).toISOString(),error:"article-not-found",message:`無此文章(title="${a}",可能已下架或 URL 不正確)。`};let i=a.replace(/[_\-\s||]*(?:观察者网|觀察者網)\s*$/u,"").trim(),o=function(t){let e=t.match(/【([^】]{4,120})】/);return e?e[1].replace(/<[^>]+>/g,"").trim():null}(s)||"",l=function(t){let e=t.match(/<span[^>]*>(20\d{2}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2})<\/span>/);return e?e[1]:null}(n)||"",u=(new Date).toISOString().slice(0,10),c=te(s,{image:!0}),h=t=>String(t).replace(/"/g,'\\"'),f=`---\ntitle: "${h(i)}"\nsource: "${r}"\nauthor: "${h(o)}"\npublished: "${l}"\ncreated: ${u}\ndescription:\n---\n${c}\n`;return{status:"success",site:"guancha",mode:"fetch",url:r,title:i,author:o,published:l,chars:c.length,markdown:f}}}};return ir});
7
7
  //# sourceMappingURL=w-dwdata-hub.umd.js.map