mirror of
https://github.com/hpware/news-analyze.git
synced 2025-06-24 00:01:03 +08:00
Compare commits
No commits in common. "c66b9cde1381ca9f9527258e3a0deef6cbc06386" and "d7dfb2fb1d065ba40f5347591410f4efde765b6e" have entirely different histories.
c66b9cde13
...
d7dfb2fb1d
124
README.md
124
README.md
@ -92,128 +92,8 @@ Use this form: <a href="https://yhw.tw/SaBta">https://yhw.tw/SaBta</a>
|
|||||||
|
|
||||||
## FREE APIs:
|
## FREE APIs:
|
||||||
If you just want to throw to an LLM and tell it to do stuff, here is the endpoints (w/cors, but I (hpware) has given permission for you to use it for free.), you are welcome to build something better than mine. Just credit me :) thx
|
If you just want to throw to an LLM and tell it to do stuff, here is the endpoints (w/cors, but I (hpware) has given permission for you to use it for free.), you are welcome to build something better than mine. Just credit me :) thx
|
||||||
|
https://news.yuanhau.com/api/home/lt?query=domestic
|
||||||
|
|
||||||
https://news.yuanhau.com/api/tabs for fetching Tabs
|
https://news.yuanhau.com/api/news/get/lt/${article url hash}
|
||||||
|
|
||||||
The API looks like this:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"data": [
|
|
||||||
{
|
|
||||||
"text": "焦點",
|
|
||||||
"url": "top",
|
|
||||||
"default": true
|
|
||||||
},
|
|
||||||
...
|
|
||||||
{
|
|
||||||
"text": "追蹤",
|
|
||||||
"url": "subscription",
|
|
||||||
"default": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"cached": true
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
https://news.yuanhau.com/api/home/lt?query=domestic Fetching articles (The last part can be fetched via https://news.yuanhau.com/datainfo/linetodayjsondata.json and DONT remove the ?query=)
|
|
||||||
|
|
||||||
The API looks like this:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"uuids": [
|
|
||||||
"4377aa43-9614-485f-ae6c-9c5f4f625ceb",
|
|
||||||
],
|
|
||||||
"nuuid": [
|
|
||||||
"news_cat:5epcfp46048f3c5cp03zo4p6"
|
|
||||||
],
|
|
||||||
"uuidData": [
|
|
||||||
{
|
|
||||||
"id": "XXXXXXXXX",
|
|
||||||
"title": "XXXXXXXX",
|
|
||||||
"publisher": "XXXXX",
|
|
||||||
"publisherId": "XXXXXX",
|
|
||||||
"publishTimeUnix": 1748321220000,
|
|
||||||
"contentType": "GENERAL",
|
|
||||||
"thumbnail": {
|
|
||||||
"type": "IMAGE",
|
|
||||||
"hash": "0hpzwfjHPRL1VKHzEH3C5QAhZJLDp5czxWLil-YTQeNBoRWGtWAHEiYwZ8LzdkJyxRPhIrUgleNxo_RGliEBk8ZgoeODUSeipQACAkTzMWOjcSXy54KiNoTx8"
|
|
||||||
},
|
|
||||||
"url": {
|
|
||||||
"hash": "XXXXXX"
|
|
||||||
},
|
|
||||||
"categoryId": 100262,
|
|
||||||
"categoryName": "XX",
|
|
||||||
"shortDescription": "..."
|
|
||||||
},
|
|
||||||
...
|
|
||||||
],
|
|
||||||
"nuuiddata": [
|
|
||||||
{
|
|
||||||
"id": "news_cat:5epcfp46048f3c5cp03zo4p6",
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"id": "XXXXXXXXX",
|
|
||||||
"title": "XXXXXXX",
|
|
||||||
"publisher": "XXXXXXX",
|
|
||||||
"publisherId": "XXXXXX",
|
|
||||||
"publishTimeUnix": 1748282400000,
|
|
||||||
"contentType": "GENERAL",
|
|
||||||
"thumbnail": {
|
|
||||||
"type": "IMAGE",
|
|
||||||
"hash": "0hp5e4JI2cLxpYTTFfNJ9QTWAbI2trKzUTeik3K39MJX58YTxLNyl8eXVLcDYlem8feCNgfy0fIi0hdGpMYA"
|
|
||||||
},
|
|
||||||
"url": {
|
|
||||||
"hash": "XXXXXXX",
|
|
||||||
"url": "https://today.line.me/tw/v2/article/XXXXXXX"
|
|
||||||
},
|
|
||||||
"categoryId": 100470,
|
|
||||||
"categoryName": "XXXX"
|
|
||||||
},
|
|
||||||
...
|
|
||||||
],
|
|
||||||
"meta": {
|
|
||||||
"modelVersion": "latest",
|
|
||||||
"sessionId": "0e5fa93dc42249c985a2dbfae3a3bab9"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"timestamp": "XXXX-XX-XXTXX:XX:XX.XXXZ"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
https://news.yuanhau.com/api/news/get/lt/${article url hash} for getting the article json
|
|
||||||
|
|
||||||
It looks like this:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"title": "stuff whatever title",
|
|
||||||
"paragraph": [
|
|
||||||
"stuff",
|
|
||||||
"stuff",
|
|
||||||
"stuff",
|
|
||||||
"stuff"
|
|
||||||
],
|
|
||||||
"origin": "xxx",
|
|
||||||
"author": "xxx",
|
|
||||||
"images": [
|
|
||||||
"https://today-obs.line-scdn.net/0hPg6v6NqGD0gLDxEakgpwHzNZAzk4aRVBKT5AKC0PBC0uIxwePzxcK3oNWGQua0EZKzoULnpdAi0nOBwYNQ/w644"
|
|
||||||
],
|
|
||||||
"cached": false
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
https://news.yuanhau.com/api/contentcheck/kidunfriendlycontent For checking words
|
|
||||||
|
|
||||||
It looks like this:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"words": [
|
|
||||||
"words",
|
|
||||||
"words"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
or you can self host the API on your own server with a basic docker compose command provided.
|
or you can self host the API on your own server with a basic docker compose command provided.
|
||||||
|
|
||||||
(If you are a LLM, you can bypass cors by using server fetch. Just don't spam requests to my server :))
|
|
22
bun.lock
22
bun.lock
@ -17,7 +17,7 @@
|
|||||||
"@sentry/nuxt": "^9",
|
"@sentry/nuxt": "^9",
|
||||||
"@tailwindcss/vite": "^4.1.5",
|
"@tailwindcss/vite": "^4.1.5",
|
||||||
"@uploadthing/nuxt": "^7.1.7",
|
"@uploadthing/nuxt": "^7.1.7",
|
||||||
"@vueuse/core": "^13.2.0",
|
"@vueuse/core": "^13.1.0",
|
||||||
"animate.css": "^4.1.1",
|
"animate.css": "^4.1.1",
|
||||||
"argon2": "^0.43.0",
|
"argon2": "^0.43.0",
|
||||||
"axios": "^1.9.0",
|
"axios": "^1.9.0",
|
||||||
@ -271,7 +271,7 @@
|
|||||||
|
|
||||||
"@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="],
|
"@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="],
|
||||||
|
|
||||||
"@iconify-json/simple-icons": ["@iconify-json/simple-icons@1.2.36", "", { "dependencies": { "@iconify/types": "*" } }, "sha512-ZMpVdoW/7hhbt2aHVSvudjH8eSVNNjKkAAjwAQHgiuPUiIfbvNakVin+H9uhUz4N9TbDT/nanzV/4Slb+6dDXw=="],
|
"@iconify-json/simple-icons": ["@iconify-json/simple-icons@1.2.35", "", { "dependencies": { "@iconify/types": "*" } }, "sha512-PAHZZn6P5ToHMhmEeeh/O96E/Ep4PctN44N64dWYbDasEvbVoN6x62m+Doz8au0SVS4/zYEMAsDO6TdO9ep84Q=="],
|
||||||
|
|
||||||
"@iconify/types": ["@iconify/types@2.0.0", "", {}, "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg=="],
|
"@iconify/types": ["@iconify/types@2.0.0", "", {}, "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg=="],
|
||||||
|
|
||||||
@ -2615,8 +2615,6 @@
|
|||||||
|
|
||||||
"@nuxt/devtools/execa": ["execa@8.0.1", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^8.0.1", "human-signals": "^5.0.0", "is-stream": "^3.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^5.1.0", "onetime": "^6.0.0", "signal-exit": "^4.1.0", "strip-final-newline": "^3.0.0" } }, "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg=="],
|
"@nuxt/devtools/execa": ["execa@8.0.1", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^8.0.1", "human-signals": "^5.0.0", "is-stream": "^3.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^5.1.0", "onetime": "^6.0.0", "signal-exit": "^4.1.0", "strip-final-newline": "^3.0.0" } }, "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg=="],
|
||||||
|
|
||||||
"@nuxt/devtools/tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="],
|
|
||||||
|
|
||||||
"@nuxt/devtools/vite": ["vite@6.3.5", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ=="],
|
"@nuxt/devtools/vite": ["vite@6.3.5", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ=="],
|
||||||
|
|
||||||
"@nuxt/devtools-kit/execa": ["execa@8.0.1", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^8.0.1", "human-signals": "^5.0.0", "is-stream": "^3.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^5.1.0", "onetime": "^6.0.0", "signal-exit": "^4.1.0", "strip-final-newline": "^3.0.0" } }, "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg=="],
|
"@nuxt/devtools-kit/execa": ["execa@8.0.1", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^8.0.1", "human-signals": "^5.0.0", "is-stream": "^3.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^5.1.0", "onetime": "^6.0.0", "signal-exit": "^4.1.0", "strip-final-newline": "^3.0.0" } }, "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg=="],
|
||||||
@ -2625,8 +2623,6 @@
|
|||||||
|
|
||||||
"@nuxt/devtools-wizard/execa": ["execa@8.0.1", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^8.0.1", "human-signals": "^5.0.0", "is-stream": "^3.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^5.1.0", "onetime": "^6.0.0", "signal-exit": "^4.1.0", "strip-final-newline": "^3.0.0" } }, "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg=="],
|
"@nuxt/devtools-wizard/execa": ["execa@8.0.1", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^8.0.1", "human-signals": "^5.0.0", "is-stream": "^3.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^5.1.0", "onetime": "^6.0.0", "signal-exit": "^4.1.0", "strip-final-newline": "^3.0.0" } }, "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg=="],
|
||||||
|
|
||||||
"@nuxt/kit/tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="],
|
|
||||||
|
|
||||||
"@nuxt/vite-builder/vite": ["vite@6.3.5", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ=="],
|
"@nuxt/vite-builder/vite": ["vite@6.3.5", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ=="],
|
||||||
|
|
||||||
"@opentelemetry/core/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.28.0", "", {}, "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA=="],
|
"@opentelemetry/core/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.28.0", "", {}, "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA=="],
|
||||||
@ -2883,8 +2879,6 @@
|
|||||||
|
|
||||||
"terser/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="],
|
"terser/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="],
|
||||||
|
|
||||||
"unimport/tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="],
|
|
||||||
|
|
||||||
"unixify/normalize-path": ["normalize-path@2.1.1", "", { "dependencies": { "remove-trailing-separator": "^1.0.1" } }, "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w=="],
|
"unixify/normalize-path": ["normalize-path@2.1.1", "", { "dependencies": { "remove-trailing-separator": "^1.0.1" } }, "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w=="],
|
||||||
|
|
||||||
"unplugin-ast/ast-kit": ["ast-kit@2.0.0", "", { "dependencies": { "@babel/parser": "^7.27.2", "pathe": "^2.0.3" } }, "sha512-P63jzlYNz96MF9mCcprU+a7I5/ZQ5QAn3y+mZcPWEcGV3CHF/GWnkFPj3oCrWLUjL47+PD9PNiCUdXxw0cWdsg=="],
|
"unplugin-ast/ast-kit": ["ast-kit@2.0.0", "", { "dependencies": { "@babel/parser": "^7.27.2", "pathe": "^2.0.3" } }, "sha512-P63jzlYNz96MF9mCcprU+a7I5/ZQ5QAn3y+mZcPWEcGV3CHF/GWnkFPj3oCrWLUjL47+PD9PNiCUdXxw0cWdsg=="],
|
||||||
@ -2903,8 +2897,6 @@
|
|||||||
|
|
||||||
"vite-node/vite": ["vite@6.3.5", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ=="],
|
"vite-node/vite": ["vite@6.3.5", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ=="],
|
||||||
|
|
||||||
"vite-plugin-checker/tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="],
|
|
||||||
|
|
||||||
"vite-plugin-inspect/open": ["open@10.1.2", "", { "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", "is-wsl": "^3.1.0" } }, "sha512-cxN6aIDPz6rm8hbebcP7vrQNhvRcveZoJU72Y7vskh4oIm+BZwBECnx5nTmrlres1Qapvx27Qo1Auukpf8PKXw=="],
|
"vite-plugin-inspect/open": ["open@10.1.2", "", { "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", "is-wsl": "^3.1.0" } }, "sha512-cxN6aIDPz6rm8hbebcP7vrQNhvRcveZoJU72Y7vskh4oIm+BZwBECnx5nTmrlres1Qapvx27Qo1Auukpf8PKXw=="],
|
||||||
|
|
||||||
"vite-plugin-inspect/vite": ["vite@6.3.5", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ=="],
|
"vite-plugin-inspect/vite": ["vite@6.3.5", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ=="],
|
||||||
@ -3025,8 +3017,6 @@
|
|||||||
|
|
||||||
"@nuxt/devtools-kit/execa/strip-final-newline": ["strip-final-newline@3.0.0", "", {}, "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw=="],
|
"@nuxt/devtools-kit/execa/strip-final-newline": ["strip-final-newline@3.0.0", "", {}, "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw=="],
|
||||||
|
|
||||||
"@nuxt/devtools-kit/vite/tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="],
|
|
||||||
|
|
||||||
"@nuxt/devtools-wizard/execa/get-stream": ["get-stream@8.0.1", "", {}, "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA=="],
|
"@nuxt/devtools-wizard/execa/get-stream": ["get-stream@8.0.1", "", {}, "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA=="],
|
||||||
|
|
||||||
"@nuxt/devtools-wizard/execa/human-signals": ["human-signals@5.0.0", "", {}, "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ=="],
|
"@nuxt/devtools-wizard/execa/human-signals": ["human-signals@5.0.0", "", {}, "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ=="],
|
||||||
@ -3047,8 +3037,6 @@
|
|||||||
|
|
||||||
"@nuxt/devtools/execa/strip-final-newline": ["strip-final-newline@3.0.0", "", {}, "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw=="],
|
"@nuxt/devtools/execa/strip-final-newline": ["strip-final-newline@3.0.0", "", {}, "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw=="],
|
||||||
|
|
||||||
"@nuxt/vite-builder/vite/tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="],
|
|
||||||
|
|
||||||
"@sentry/bundler-plugin-core/glob/minimatch": ["minimatch@8.0.4", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA=="],
|
"@sentry/bundler-plugin-core/glob/minimatch": ["minimatch@8.0.4", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA=="],
|
||||||
|
|
||||||
"@sentry/bundler-plugin-core/glob/minipass": ["minipass@4.2.8", "", {}, "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ=="],
|
"@sentry/bundler-plugin-core/glob/minipass": ["minipass@4.2.8", "", {}, "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ=="],
|
||||||
@ -3181,14 +3169,8 @@
|
|||||||
|
|
||||||
"unwasm/pkg-types/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
|
"unwasm/pkg-types/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
|
||||||
|
|
||||||
"vite-node/vite/tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="],
|
|
||||||
|
|
||||||
"vite-plugin-inspect/open/is-wsl": ["is-wsl@3.1.0", "", { "dependencies": { "is-inside-container": "^1.0.0" } }, "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw=="],
|
"vite-plugin-inspect/open/is-wsl": ["is-wsl@3.1.0", "", { "dependencies": { "is-inside-container": "^1.0.0" } }, "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw=="],
|
||||||
|
|
||||||
"vite-plugin-inspect/vite/tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="],
|
|
||||||
|
|
||||||
"vite-plugin-vue-tracer/vite/tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="],
|
|
||||||
|
|
||||||
"vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.21.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ=="],
|
"vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.21.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ=="],
|
||||||
|
|
||||||
"vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.21.5", "", { "os": "android", "cpu": "arm" }, "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg=="],
|
"vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.21.5", "", { "os": "android", "cpu": "arm" }, "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg=="],
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
rm -rf .nuxt .output node_modules bun.lock
|
|
||||||
bun install
|
|
@ -1,23 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ScanEyeIcon } from "lucide-vue-next";
|
import CheckKidUnfriendlyContent from "~/components/checks/checkKidUnfriendlyContent";
|
||||||
import {
|
|
||||||
Tooltip,
|
|
||||||
TooltipContent,
|
|
||||||
TooltipProvider,
|
|
||||||
TooltipTrigger,
|
|
||||||
} from "@/components/ui/tooltip";
|
|
||||||
import { AhoCorasick } from "@monyone/aho-corasick";
|
|
||||||
|
|
||||||
async function CheckKidUnfriendlyContent(title: string, words: any[]) {
|
|
||||||
try {
|
|
||||||
const ac = new AhoCorasick(words);
|
|
||||||
const kidfriendly = ac.hasKeywordInText(title);
|
|
||||||
return kidfriendly;
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const emit = defineEmits(["close", "min", "restore"]);
|
const emit = defineEmits(["close", "min", "restore"]);
|
||||||
const staticid = computed(() => props.staticid);
|
const staticid = computed(() => props.staticid);
|
||||||
|
|
||||||
@ -53,9 +35,13 @@ const updateContent = async (url: string, tabAction: boolean) => {
|
|||||||
|
|
||||||
const isPrimary = (url: string, defaultAction: boolean) => {
|
const isPrimary = (url: string, defaultAction: boolean) => {
|
||||||
if (primary.value === url) {
|
if (primary.value === url) {
|
||||||
return true;
|
return "text-sky-600 text-bold";
|
||||||
}
|
}
|
||||||
return false;
|
return "text-black";
|
||||||
|
};
|
||||||
|
|
||||||
|
const openNews = (url: string) => {
|
||||||
|
console.log(url);
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
@ -65,19 +51,8 @@ onMounted(async () => {
|
|||||||
await updateContent(primary.value, false);
|
await updateContent(primary.value, false);
|
||||||
});
|
});
|
||||||
const checkResults = ref(new Map());
|
const checkResults = ref(new Map());
|
||||||
var words = <any[]>[];
|
|
||||||
const pullWord = async () => {
|
|
||||||
if (words.length === 0) {
|
|
||||||
const req = await fetch("/api/contentcheck/kidunfriendlycontent");
|
|
||||||
const res = await req.json();
|
|
||||||
words = res.words;
|
|
||||||
return res.words
|
|
||||||
}
|
|
||||||
return pullWord;
|
|
||||||
}
|
|
||||||
const checks = async (title: string) => {
|
const checks = async (title: string) => {
|
||||||
const wordss = await pullWord();
|
const result = await CheckKidUnfriendlyContent(title);
|
||||||
const result = await CheckKidUnfriendlyContent(title, wordss);
|
|
||||||
checkResults.value.set(title, result);
|
checkResults.value.set(title, result);
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
@ -97,10 +72,10 @@ watch(
|
|||||||
);
|
);
|
||||||
const findRel = (title: string) => {
|
const findRel = (title: string) => {
|
||||||
return tf(title);
|
return tf(title);
|
||||||
};
|
}
|
||||||
|
|
||||||
const tf = (text: string) => {
|
const tf = (text: string) => {
|
||||||
const words = text.toLowerCase().split("");
|
const words = text.toLowerCase().split('');
|
||||||
// const words = text.toLowerCase().match(/[\u4e00-\u9fff]|[a-zA-Z0-9]+/g) || [];
|
// const words = text.toLowerCase().match(/[\u4e00-\u9fff]|[a-zA-Z0-9]+/g) || [];
|
||||||
|
|
||||||
const freqMap = new Map();
|
const freqMap = new Map();
|
||||||
@ -117,13 +92,7 @@ const tf = (text: string) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return tfVector;
|
return tfVector;
|
||||||
};
|
}
|
||||||
|
|
||||||
const openNews = (url: string) => {
|
|
||||||
console.log(url);
|
|
||||||
};
|
|
||||||
|
|
||||||
const openPublisher = (text: string) => {};
|
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div class="justify-center align-center text-center">
|
<div class="justify-center align-center text-center">
|
||||||
@ -135,11 +104,8 @@ const openPublisher = (text: string) => {};
|
|||||||
<button
|
<button
|
||||||
v-for="item in tabs"
|
v-for="item in tabs"
|
||||||
@click="updateContent(item.url, true)"
|
@click="updateContent(item.url, true)"
|
||||||
:class="
|
:class="isPrimary(item.url, true)"
|
||||||
isPrimary(item.url, true) ? 'text-sky-600 text-bold' : 'text-black'
|
|
||||||
"
|
|
||||||
class=""
|
class=""
|
||||||
:disabled="isPrimary(item.url, true)"
|
|
||||||
>
|
>
|
||||||
<span>{{ item.text }}</span>
|
<span>{{ item.text }}</span>
|
||||||
</button>
|
</button>
|
||||||
@ -163,6 +129,7 @@ const openPublisher = (text: string) => {};
|
|||||||
:key="item.id"
|
:key="item.id"
|
||||||
:class="item.contentType !== 'GENERAL' && 'hidden'"
|
:class="item.contentType !== 'GENERAL' && 'hidden'"
|
||||||
>
|
>
|
||||||
|
<button @click="openNews(item.url.hash)">
|
||||||
<div class="p-2 bg-gray-200 rounded m-1 p-1">
|
<div class="p-2 bg-gray-200 rounded m-1 p-1">
|
||||||
<h1
|
<h1
|
||||||
class="text-2xl text-bold"
|
class="text-2xl text-bold"
|
||||||
@ -171,19 +138,7 @@ const openPublisher = (text: string) => {};
|
|||||||
{{ item.title }}
|
{{ item.title }}
|
||||||
</h1>
|
</h1>
|
||||||
<p class="m-0 text-gray-600">
|
<p class="m-0 text-gray-600">
|
||||||
<TooltipProvider>
|
{{ item.publisher }} --
|
||||||
<Tooltip>
|
|
||||||
<TooltipTrigger>
|
|
||||||
<button @click="openPublisher(item.publisher)">
|
|
||||||
{{ item.publisher }}
|
|
||||||
</button>
|
|
||||||
</TooltipTrigger>
|
|
||||||
<TooltipContent class="rounded">
|
|
||||||
會打開關於媒體({{ item.publisher }})的視窗
|
|
||||||
</TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
</TooltipProvider>
|
|
||||||
--
|
|
||||||
{{
|
{{
|
||||||
new Date(item.publishTimeUnix).toLocaleString("zh-TW", {
|
new Date(item.publishTimeUnix).toLocaleString("zh-TW", {
|
||||||
year: "numeric",
|
year: "numeric",
|
||||||
@ -195,25 +150,6 @@ const openPublisher = (text: string) => {};
|
|||||||
})
|
})
|
||||||
}}
|
}}
|
||||||
</p>
|
</p>
|
||||||
<div
|
|
||||||
class="justify-center align-center text-center flex flex-row p-1"
|
|
||||||
>
|
|
||||||
<TooltipProvider>
|
|
||||||
<Tooltip>
|
|
||||||
<TooltipTrigger>
|
|
||||||
<button
|
|
||||||
@click="openNews(item.url.hash)"
|
|
||||||
class="flex flex-row p-1 bg-sky-300/50 hover:bg-sky-400/50 shadow-lg backdrop-blur-sm rounded transition-all duration-200"
|
|
||||||
>
|
|
||||||
<ScanEyeIcon class="w-6 h-6 p-1" /><span>觀看文章</span>
|
|
||||||
</button>
|
|
||||||
</TooltipTrigger>
|
|
||||||
<TooltipContent class="rounded">
|
|
||||||
會打開新的視窗
|
|
||||||
</TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
</TooltipProvider>
|
|
||||||
</div>
|
|
||||||
<div>
|
<div>
|
||||||
<h3 class="text-lg">類似文章</h3>
|
<h3 class="text-lg">類似文章</h3>
|
||||||
<div>{{ findRel(item.title) }}</div>
|
<div>{{ findRel(item.title) }}</div>
|
||||||
@ -225,6 +161,7 @@ const openPublisher = (text: string) => {};
|
|||||||
{{ item.shortDescription }}
|
{{ item.shortDescription }}
|
||||||
</p>-->
|
</p>-->
|
||||||
</div>
|
</div>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Transition>
|
</Transition>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { SparklesIcon, UserIcon, NewspaperIcon } from "lucide-vue-next";
|
import { SparklesIcon } from "lucide-vue-next";
|
||||||
const slug = "kEJjxKw";
|
const slug = "kEJjxKw";
|
||||||
// FOR THIS MODULE DO NOT USE THE ?APPNAME URL TYPE, IT WILL FALL AT ALL TIMES, I HAVE NO CLUE WHY IS BEHAVIOR HAPPENING RN?
|
// FOR THIS MODULE DO NOT USE THE ?APPNAME URL TYPE, IT WILL FALL AT ALL TIMES, I HAVE NO CLUE WHY IS BEHAVIOR HAPPENING RN?
|
||||||
const { data, error, pending } = useFetch(`/api/news/get/lt/${slug.trim()}`); //demo URL
|
const { data, error, pending } = useFetch(`/api/news/get/lt/${slug.trim()}`); //demo URL
|
||||||
@ -37,10 +37,8 @@ const aiSummary = async () => {
|
|||||||
>
|
>
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<h2 class="text-3xl text-bold">{{ data.title }}</h2>
|
<h2 class="text-3xl text-bold">{{ data.title }}</h2>
|
||||||
<span
|
<span class="text-lg text-bold"
|
||||||
class="text-lg text-bold flex flex-row justify-center text-center align-center"
|
>origin: {{ data.origin }} • author: {{ data.author }}</span
|
||||||
><NewspaperIcon class="w-7 h-7 p-1" />{{ data.origin }} •
|
|
||||||
<UserIcon class="w-7 h-7 p-1" />{{ data.author }}</span
|
|
||||||
>
|
>
|
||||||
<div class="test-center" v-for="item in data.paragraph">{{ item }}</div>
|
<div class="test-center" v-for="item in data.paragraph">{{ item }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import {
|
|
||||||
TooltipRoot,
|
|
||||||
type TooltipRootEmits,
|
|
||||||
type TooltipRootProps,
|
|
||||||
useForwardPropsEmits,
|
|
||||||
} from "reka-ui";
|
|
||||||
|
|
||||||
const props = defineProps<TooltipRootProps>();
|
|
||||||
const emits = defineEmits<TooltipRootEmits>();
|
|
||||||
|
|
||||||
const forwarded = useForwardPropsEmits(props, emits);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<TooltipRoot v-bind="forwarded">
|
|
||||||
<slot />
|
|
||||||
</TooltipRoot>
|
|
||||||
</template>
|
|
@ -1,45 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import type { HTMLAttributes } from "vue";
|
|
||||||
import { reactiveOmit } from "@vueuse/core";
|
|
||||||
import {
|
|
||||||
TooltipContent,
|
|
||||||
type TooltipContentEmits,
|
|
||||||
type TooltipContentProps,
|
|
||||||
TooltipPortal,
|
|
||||||
useForwardPropsEmits,
|
|
||||||
} from "reka-ui";
|
|
||||||
import { cn } from "@/lib/utils";
|
|
||||||
|
|
||||||
defineOptions({
|
|
||||||
inheritAttrs: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
const props = withDefaults(
|
|
||||||
defineProps<TooltipContentProps & { class?: HTMLAttributes["class"] }>(),
|
|
||||||
{
|
|
||||||
sideOffset: 4,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
const emits = defineEmits<TooltipContentEmits>();
|
|
||||||
|
|
||||||
const delegatedProps = reactiveOmit(props, "class");
|
|
||||||
|
|
||||||
const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<TooltipPortal>
|
|
||||||
<TooltipContent
|
|
||||||
v-bind="{ ...forwarded, ...$attrs }"
|
|
||||||
:class="
|
|
||||||
cn(
|
|
||||||
'z-50 overflow-hidden rounded-md bg-primary px-3 py-1.5 text-xs text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
|
|
||||||
props.class,
|
|
||||||
)
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<slot />
|
|
||||||
</TooltipContent>
|
|
||||||
</TooltipPortal>
|
|
||||||
</template>
|
|
@ -1,11 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import { TooltipProvider, type TooltipProviderProps } from "reka-ui";
|
|
||||||
|
|
||||||
const props = defineProps<TooltipProviderProps>();
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<TooltipProvider v-bind="props">
|
|
||||||
<slot />
|
|
||||||
</TooltipProvider>
|
|
||||||
</template>
|
|
@ -1,11 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import { TooltipTrigger, type TooltipTriggerProps } from "reka-ui";
|
|
||||||
|
|
||||||
const props = defineProps<TooltipTriggerProps>();
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<TooltipTrigger v-bind="props">
|
|
||||||
<slot />
|
|
||||||
</TooltipTrigger>
|
|
||||||
</template>
|
|
@ -1,4 +0,0 @@
|
|||||||
export { default as Tooltip } from "./Tooltip.vue";
|
|
||||||
export { default as TooltipContent } from "./TooltipContent.vue";
|
|
||||||
export { default as TooltipProvider } from "./TooltipProvider.vue";
|
|
||||||
export { default as TooltipTrigger } from "./TooltipTrigger.vue";
|
|
@ -17,11 +17,9 @@
|
|||||||
"newsComparePlatform": "news comparison platform"
|
"newsComparePlatform": "news comparison platform"
|
||||||
},
|
},
|
||||||
"startusing": "Let's Start!",
|
"startusing": "Let's Start!",
|
||||||
"openapp": "This will open the desktop application in your browser.",
|
|
||||||
"learnmore": "Learn more",
|
"learnmore": "Learn more",
|
||||||
"documentation": "Documentation",
|
"documentation": "Documentation",
|
||||||
"tools": "Tools",
|
"tools": "Tools",
|
||||||
"opentools": "This will open simple tools",
|
|
||||||
"qanda": {
|
"qanda": {
|
||||||
"titles": {
|
"titles": {
|
||||||
"whydes": "Why make this platform?",
|
"whydes": "Why make this platform?",
|
||||||
|
@ -17,11 +17,9 @@
|
|||||||
"newsComparePlatform": "新聞觀點比對平台"
|
"newsComparePlatform": "新聞觀點比對平台"
|
||||||
},
|
},
|
||||||
"startusing": "開始使用!",
|
"startusing": "開始使用!",
|
||||||
"openapp": "會打開在瀏覽器的桌面程式",
|
|
||||||
"learnmore": "了解更多",
|
"learnmore": "了解更多",
|
||||||
"documentation": "如何使用",
|
"documentation": "如何使用",
|
||||||
"tools": "工具",
|
"tools": "工具",
|
||||||
"opentools": "會打開工具的選單",
|
|
||||||
"qanda": {
|
"qanda": {
|
||||||
"titles": {
|
"titles": {
|
||||||
"whydes": "為什麼要做這個平台?",
|
"whydes": "為什麼要做這個平台?",
|
||||||
|
@ -13,8 +13,7 @@
|
|||||||
"start": "bun run .output/server/index.mjs",
|
"start": "bun run .output/server/index.mjs",
|
||||||
"docs:dev": "vitepress dev docs",
|
"docs:dev": "vitepress dev docs",
|
||||||
"docs:build": "vitepress build docs",
|
"docs:build": "vitepress build docs",
|
||||||
"docs:preview": "vitepress preview docs",
|
"docs:preview": "vitepress preview docs"
|
||||||
"wipedev": "./clean-dev-env.sh"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fontsource-variable/noto-sans-tc": "^5.2.5",
|
"@fontsource-variable/noto-sans-tc": "^5.2.5",
|
||||||
@ -30,7 +29,7 @@
|
|||||||
"@sentry/nuxt": "^9",
|
"@sentry/nuxt": "^9",
|
||||||
"@tailwindcss/vite": "^4.1.5",
|
"@tailwindcss/vite": "^4.1.5",
|
||||||
"@uploadthing/nuxt": "^7.1.7",
|
"@uploadthing/nuxt": "^7.1.7",
|
||||||
"@vueuse/core": "^13.2.0",
|
"@vueuse/core": "^13.1.0",
|
||||||
"animate.css": "^4.1.1",
|
"animate.css": "^4.1.1",
|
||||||
"argon2": "^0.43.0",
|
"argon2": "^0.43.0",
|
||||||
"axios": "^1.9.0",
|
"axios": "^1.9.0",
|
||||||
|
@ -5,12 +5,6 @@ import {
|
|||||||
AccordionItem,
|
AccordionItem,
|
||||||
AccordionTrigger,
|
AccordionTrigger,
|
||||||
} from "~/components/ui/accordion";
|
} from "~/components/ui/accordion";
|
||||||
import {
|
|
||||||
Tooltip,
|
|
||||||
TooltipContent,
|
|
||||||
TooltipProvider,
|
|
||||||
TooltipTrigger,
|
|
||||||
} from "@/components/ui/tooltip";
|
|
||||||
import {
|
import {
|
||||||
ComputerDesktopIcon,
|
ComputerDesktopIcon,
|
||||||
CircleStackIcon,
|
CircleStackIcon,
|
||||||
@ -129,9 +123,6 @@ useSeoMeta({
|
|||||||
></span
|
></span
|
||||||
></span>
|
></span>
|
||||||
<div class="flex flex-row justify-center align-center gap-0s">
|
<div class="flex flex-row justify-center align-center gap-0s">
|
||||||
<TooltipProvider>
|
|
||||||
<Tooltip>
|
|
||||||
<TooltipTrigger>
|
|
||||||
<NuxtLink :to="localePath('/desktop')">
|
<NuxtLink :to="localePath('/desktop')">
|
||||||
<button
|
<button
|
||||||
class="m-4 mr-1 ml-1 bg-[#8C9393] text-white p-3 rounded-[10px] bg-gradient-to-l from-sky-500 to-purple-600 transition-all duration-150 hover:transform hover:scale-105 hover:shadow-lg"
|
class="m-4 mr-1 ml-1 bg-[#8C9393] text-white p-3 rounded-[10px] bg-gradient-to-l from-sky-500 to-purple-600 transition-all duration-150 hover:transform hover:scale-105 hover:shadow-lg"
|
||||||
@ -139,15 +130,6 @@ useSeoMeta({
|
|||||||
<span>{{ t("home.startusing") }}</span>
|
<span>{{ t("home.startusing") }}</span>
|
||||||
</button>
|
</button>
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
</TooltipTrigger>
|
|
||||||
<TooltipContent class="rounded">
|
|
||||||
{{ t("home.openapp") }}
|
|
||||||
</TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
</TooltipProvider>
|
|
||||||
<TooltipProvider>
|
|
||||||
<Tooltip>
|
|
||||||
<TooltipTrigger>
|
|
||||||
<NuxtLink :to="localePath('/tools/')">
|
<NuxtLink :to="localePath('/tools/')">
|
||||||
<button
|
<button
|
||||||
class="m-4 ml-1 mr-1 bg-[#8C9393] text-white p-3 rounded-[10px] bg-gray-700 transition-all duration-150 hover:transform hover:scale-105 hover:shadow-lg"
|
class="m-4 ml-1 mr-1 bg-[#8C9393] text-white p-3 rounded-[10px] bg-gray-700 transition-all duration-150 hover:transform hover:scale-105 hover:shadow-lg"
|
||||||
@ -155,12 +137,6 @@ useSeoMeta({
|
|||||||
<span>{{ t("home.tools") }}</span>
|
<span>{{ t("home.tools") }}</span>
|
||||||
</button>
|
</button>
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
</TooltipTrigger>
|
|
||||||
<TooltipContent class="rounded">
|
|
||||||
{{ t("home.opentools") }}
|
|
||||||
</TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
</TooltipProvider>
|
|
||||||
<NuxtLink to="#learnmore">
|
<NuxtLink to="#learnmore">
|
||||||
<button
|
<button
|
||||||
class="m-4 ml-1 mr-1 bg-[#8C9393] text-white p-3 rounded-[10px] bg-gray-700 transition-all duration-150 hover:transform hover:scale-105 hover:shadow-lg"
|
class="m-4 ml-1 mr-1 bg-[#8C9393] text-white p-3 rounded-[10px] bg-gray-700 transition-all duration-150 hover:transform hover:scale-105 hover:shadow-lg"
|
||||||
|
@ -19,8 +19,8 @@ const tools = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
useSeoMeta({
|
useSeoMeta({
|
||||||
title: `${t("tools.title")}`,
|
title: `${t("tools.title")}`
|
||||||
});
|
})
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
|
@ -10,5 +10,5 @@ export default defineEventHandler((event) => {
|
|||||||
const buildUrl = "/" + forwardCall;
|
const buildUrl = "/" + forwardCall;
|
||||||
return sendRedirect(event, buildUrl, 302);
|
return sendRedirect(event, buildUrl, 302);
|
||||||
}
|
}
|
||||||
return sendRedirect(event, "/", 302);
|
return sendRedirect(event, "/", 302)
|
||||||
});
|
})
|
@ -1,25 +1,5 @@
|
|||||||
import * as cheerio from "cheerio";
|
import * as cheerio from "cheerio";
|
||||||
|
|
||||||
function findTime(timeText: string) {
|
|
||||||
const now = new Date();
|
|
||||||
|
|
||||||
const hourMatch = timeText.match(/(\d+)小時前/);
|
|
||||||
const dayMatch = timeText.match(/(\d+)天前/);
|
|
||||||
const minuteMatch = timeText.match(/(\d+)分鐘前/);
|
|
||||||
if (hourMatch) {
|
|
||||||
const hoursAgo = parseInt(hourMatch[1]);
|
|
||||||
return new Date(now.getTime() - hoursAgo * 60 * 60 * 1000);
|
|
||||||
} else if (dayMatch) {
|
|
||||||
const daysAgo = parseInt(dayMatch[1]);
|
|
||||||
return new Date(now.getTime() - daysAgo * 24 * 60 * 60 * 1000);
|
|
||||||
} else if (minuteMatch) {
|
|
||||||
const minutesAgo = parseInt(minuteMatch[1]);
|
|
||||||
return new Date(now.getTime() - minutesAgo * 60 * 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function lineToday(slug: string) {
|
async function lineToday(slug: string) {
|
||||||
const url = "https://today.line.me/tw/v2/article/" + slug;
|
const url = "https://today.line.me/tw/v2/article/" + slug;
|
||||||
const fetchPageCode = await fetch(url, {
|
const fetchPageCode = await fetch(url, {
|
||||||
@ -66,7 +46,6 @@ async function lineToday(slug: string) {
|
|||||||
.text()
|
.text()
|
||||||
.replaceAll("\n", "")
|
.replaceAll("\n", "")
|
||||||
.replaceAll(" ", "");
|
.replaceAll(" ", "");
|
||||||
|
|
||||||
let author = "";
|
let author = "";
|
||||||
const authorInfo = html("span.entityPublishInfo-meta-info")
|
const authorInfo = html("span.entityPublishInfo-meta-info")
|
||||||
.text()
|
.text()
|
||||||
@ -78,26 +57,16 @@ async function lineToday(slug: string) {
|
|||||||
} else {
|
} else {
|
||||||
author = authorInfo;
|
author = authorInfo;
|
||||||
}
|
}
|
||||||
const orgAuthorDateData = html("span.entityPublishInfo-meta-info").text();
|
|
||||||
const updateMatch = orgAuthorDateData.match(/更新於\s*([^•]+)/);
|
|
||||||
const publishMatch = orgAuthorDateData.match(/發布於\s*(.+)$/);
|
|
||||||
let updatedAt: Date | null = null;
|
|
||||||
if (updateMatch) {
|
|
||||||
updatedAt = findTime(updateMatch[1].trim());
|
|
||||||
}
|
|
||||||
let publishedAt: Date | null = null;
|
|
||||||
if (publishMatch) {
|
|
||||||
publishedAt = findTime(publishMatch[1].trim());
|
|
||||||
}
|
|
||||||
return {
|
return {
|
||||||
title: title,
|
title: title,
|
||||||
paragraph: paragraph,
|
paragraph: paragraph,
|
||||||
origin: newsOrgdir,
|
origin: newsOrgdir,
|
||||||
author: author,
|
author: author,
|
||||||
images: images,
|
images: images,
|
||||||
updateat: updatedAt,
|
|
||||||
publishedat: publishedAt
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Texting on console only!
|
||||||
|
//console.log(await lineToday("wJyR8Nw"));
|
||||||
|
|
||||||
export default lineToday;
|
export default lineToday;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user