From ce0baddc7851ddd5dceeae06d88ec7b9699b3648 Mon Sep 17 00:00:00 2001 From: ourongxing Date: Wed, 17 Sep 2025 13:44:19 +0800 Subject: [PATCH 01/17] fix: weibo source --- server/sources/weibo.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/server/sources/weibo.ts b/server/sources/weibo.ts index 53a6ed9..878b183 100644 --- a/server/sources/weibo.ts +++ b/server/sources/weibo.ts @@ -123,8 +123,14 @@ export interface Actionlog2 { } export default defineSource(async () => { - const url = "https://m.weibo.cn/api/container/getIndex?containerid=106003type%3D25%26t%3D3%26disable_hot%3D1%26filter_type%3Drealtimehot" - const res: Root = await myFetch(url) + const url = "https://m.weibo.cn/api/container/getIndex?containerid=106003type%3D25%26t%3D3%26disable_hot%3D1%26filter_type%3Drealtimehot&title=%E5%BE%AE%E5%8D%9A%E7%83%AD%E6%90%9C&extparam=filter_type%3Drealtimehot%26mi_cid%3D100103%26pos%3D0_0%26c_type%3D30%26display_time%3D1540538388&luicode=10000011&lfid=231583" + const res: Root = await myFetch(url, { + headers: { + "referer": "https://s.weibo.com/top/summary?cate=realtimehot", + "mweibo-pwa": "1", + "x-requested-with": "XMLHttpRequest", + }, + }) return res.data.cards[0].card_group .filter((k, i) => i !== 0 && k.desc && !k.actionlog?.ext.includes("ads_word")) .map((k) => { From 5a07c02ad087b2cd6fda705469b33c8002cfd887 Mon Sep 17 00:00:00 2001 From: ourongxing Date: Wed, 17 Sep 2025 14:00:40 +0800 Subject: [PATCH 02/17] fix: adjust layout in NewsListHot component for better alignment --- src/components/column/card.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/column/card.tsx b/src/components/column/card.tsx index 725924c..a7dc95e 100644 --- a/src/components/column/card.tsx +++ b/src/components/column/card.tsx @@ -236,11 +236,11 @@ function NewsListHot({ items }: { items: NewsItem[] }) { key={item.id} title={item.extra?.hover} className={$( - "flex gap-2 items-start items-stretch relative cursor-pointer [&_*]:cursor-pointer transition-all", + "flex gap-2 items-center items-stretch relative cursor-pointer [&_*]:cursor-pointer transition-all", "hover:bg-neutral-400/10 rounded-md pr-1 visited:(text-neutral-400)", )} > - + {i + 1} {!!item.extra?.diff && } From f2698ba2f01bc98eabff780c291e0016f447f24f Mon Sep 17 00:00:00 2001 From: ourongxing Date: Wed, 17 Sep 2025 14:01:08 +0800 Subject: [PATCH 03/17] chore: release v0.0.35 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d4d4ac7..7b1e80d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "newsnow", "type": "module", - "version": "0.0.34", + "version": "0.0.35", "private": true, "packageManager": "pnpm@10.14.0+sha512.ad27a79641b49c3e481a16a805baa71817a04bbe06a38d17e60e2eaee83f6a146c6a688125f5792e48dd5ba30e7da52a5cda4c3992b9ccf333f9ce223af84748", "author": { From 5627cbef601a4f6db2f55920ffdf38ba616e598e Mon Sep 17 00:00:00 2001 From: Kecheng Wang <935017625@qq.com> Date: Mon, 27 Oct 2025 23:38:39 +0800 Subject: [PATCH 04/17] fix: kaopu source (#238) Co-authored-by: kanson --- server/sources/kaopu.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/sources/kaopu.ts b/server/sources/kaopu.ts index aac71a9..41a9178 100644 --- a/server/sources/kaopu.ts +++ b/server/sources/kaopu.ts @@ -7,7 +7,7 @@ type Res = { title: string }[] export default defineSource(async () => { - const res = await Promise.all(["https://kaopucdn.azureedge.net/jsondata/news_list_beta_hans_0.json", "https://kaopucdn.azureedge.net/jsondata/news_list_beta_hans_1.json"].map(url => myFetch(url) as Promise)) + const res = await Promise.all(["https://kaopustorage.blob.core.windows.net/jsondata/news_list_beta_hans_0.json", "https://kaopustorage.blob.core.windows.net/jsondata/news_list_beta_hans_1.json"].map(url => myFetch(url) as Promise)) return res.flat().filter(k => ["财新", "公视"].every(h => k.publisher !== h)).map((k) => { return { id: k.link, From 4b89a57889e26f02e72b5a715528ced260e32ce1 Mon Sep 17 00:00:00 2001 From: likanug <14996214+bruceblink@users.noreply.github.com> Date: Mon, 27 Oct 2025 23:38:59 +0800 Subject: [PATCH 05/17] =?UTF-8?q?feat:=20Add=20new=20source:=20=E8=B1=86?= =?UTF-8?q?=E7=93=A3=E7=83=AD=E9=97=A8=E7=94=B5=E5=BD=B1=20(#237)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: Add new source 豆瓣热门电影 * refactor: Simplify the if condition --- public/icons/douban.png | Bin 0 -> 5686 bytes server/glob.d.ts | 1 + server/sources/douban.ts | 46 +++++++++++++++++++++++++++++++++++++++ shared/pinyin.json | 3 ++- shared/pre-sources.ts | 12 +++++++--- shared/sources.json | 9 ++++++++ 6 files changed, 67 insertions(+), 4 deletions(-) create mode 100644 public/icons/douban.png create mode 100644 server/sources/douban.ts diff --git a/public/icons/douban.png b/public/icons/douban.png new file mode 100644 index 0000000000000000000000000000000000000000..8522c178da0caced6a3e3d9c91336eda86b611e3 GIT binary patch literal 5686 zcmZQzU}Ruo5D;Jh(i{vKtPBil3=9kk3Lw4$!wR5yA5csKCc6o|nf%niXH zHV6xrGcZV%@H0r22{7olC^1-d=rP#z=rcI?nlZRev|wd`z!}nib8UFnJ!|?atABKPb{xSUj55oV!&Ke~~Ltr!n1||g9QLSZX5D-NIz!F46 z9tntmRSU}tGBOIv3o|eVN1_zBeRXLPm~*`EX9Z)E#N z*=XqwSohKt5K3z_wH#>pV7DKe`z9Xfga^xy-#`9K)o@|>10)8Lg8`5pY-W)ocJ=us zn6dx&-P(!MT#y_Lfb@`K7rGwpHW`?aV7h8^0Zwy4a>xLr7u`Hk`FU$nkd6Fr+M|xs zOpqKh0O=*wK6LeaZ|;B_`Q*c+|N0#Ycri!~41n~an@24F^0NytV<@IUW)W*IOx<9z z|MsgJ|2uX!kc2^cV1QEpZ@s#K { + const baseURL = "https://m.douban.com/rexxar/api/v2/subject/recent_hot/movie" + const res: HotMoviesRes = await myFetch(baseURL, { + headers: { + Referer: "https://movie.douban.com/", + Accept: "application/json, text/plain, */*", + }, + }) + return res.items.map(movie => ({ + id: movie.id, + title: `《${movie.title}》${movie.card_subtitle}`, + url: `https://movie.douban.com/subject/${movie.id}`, + extra: { + hover: movie.card_subtitle, + }, + })) +}) diff --git a/shared/pinyin.json b/shared/pinyin.json index 4d0de50..b1d2316 100644 --- a/shared/pinyin.json +++ b/shared/pinyin.json @@ -41,5 +41,6 @@ "juejin": "xitujuejin", "ifeng": "fenghuangwang-redianzixun", "chongbuluo-latest": "chongbuluo-zuixin", - "chongbuluo-hot": "chongbuluo-zuire" + "chongbuluo-hot": "chongbuluo-zuire", + "douban": "douban-remendianying" } \ No newline at end of file diff --git a/shared/pre-sources.ts b/shared/pre-sources.ts index 24229c2..61d55a3 100644 --- a/shared/pre-sources.ts +++ b/shared/pre-sources.ts @@ -413,6 +413,14 @@ export const originSources = { }, }, }, + "douban": { + name: "豆瓣", + column: "china", + title: "热门电影", + color: "green", + type: "hottest", + home: "https://www.douban.com", + }, } as const satisfies Record export function genSources() { @@ -461,10 +469,8 @@ export function genSources() { _.filter(([_, v]) => { if (v.disable === "cf" && process.env.CF_PAGES) { return false - } else if (v.disable === true) { - return false } else { - return true + return v.disable !== true } }), ) diff --git a/shared/sources.json b/shared/sources.json index 41e1a71..01bb44e 100644 --- a/shared/sources.json +++ b/shared/sources.json @@ -472,5 +472,14 @@ "color": "green", "interval": 1800000, "title": "最热" + }, + "douban": { + "title": "热门电影", + "name": "豆瓣", + "type": "hottest", + "column": "china", + "home": "https://www.douban.com", + "color": "green", + "interval": 600000 } } \ No newline at end of file From 7e6805ca87aed5ec02de9db49259074406833dd0 Mon Sep 17 00:00:00 2001 From: ourongxing Date: Mon, 27 Oct 2025 15:51:58 +0000 Subject: [PATCH 06/17] chore(source): opt display style --- server/sources/douban.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/server/sources/douban.ts b/server/sources/douban.ts index 1d7ad60..241d9ee 100644 --- a/server/sources/douban.ts +++ b/server/sources/douban.ts @@ -35,11 +35,13 @@ export default defineSource(async () => { Accept: "application/json, text/plain, */*", }, }) + console.log(res) return res.items.map(movie => ({ id: movie.id, - title: `《${movie.title}》${movie.card_subtitle}`, + title: movie.title, url: `https://movie.douban.com/subject/${movie.id}`, extra: { + info: movie.card_subtitle.split(" / ").slice(0, 3).join(" / "), hover: movie.card_subtitle, }, })) From a0941eff6339486c7bedde3ba2fb2d35faf9ba88 Mon Sep 17 00:00:00 2001 From: ourongxing Date: Mon, 27 Oct 2025 16:10:04 +0000 Subject: [PATCH 07/17] fix(source): producthunt by offical api --- example.env.server | 3 +- server/sources/douban.ts | 1 - server/sources/producthunt.ts | 62 +++++++++++++++++++++++++---------- 3 files changed, 47 insertions(+), 19 deletions(-) diff --git a/example.env.server b/example.env.server index 8c920c5..4fd731e 100644 --- a/example.env.server +++ b/example.env.server @@ -2,4 +2,5 @@ G_CLIENT_ID= G_CLIENT_SECRET= JWT_SECRET= INIT_TABLE=true -ENABLE_CACHE=true \ No newline at end of file +ENABLE_CACHE=true +PRODUCTHUNT_API_TOKEN= \ No newline at end of file diff --git a/server/sources/douban.ts b/server/sources/douban.ts index 241d9ee..7c54e86 100644 --- a/server/sources/douban.ts +++ b/server/sources/douban.ts @@ -35,7 +35,6 @@ export default defineSource(async () => { Accept: "application/json, text/plain, */*", }, }) - console.log(res) return res.items.map(movie => ({ id: movie.id, title: movie.title, diff --git a/server/sources/producthunt.ts b/server/sources/producthunt.ts index 8ebd14e..79ca023 100644 --- a/server/sources/producthunt.ts +++ b/server/sources/producthunt.ts @@ -1,28 +1,56 @@ -import * as cheerio from "cheerio" +import process from "node:process" import type { NewsItem } from "@shared/types" +const apiKey = process.env.PRODUCTHUNT_API_TOKEN +const token = `Bearer ${apiKey}` export default defineSource(async () => { - const baseURL = "https://www.producthunt.com" - const html: any = await myFetch(baseURL) - const $ = cheerio.load(html) - const $main = $("[data-test=homepage-section-0] [data-test^=post-item]") + if (!apiKey) { + throw new Error("PRODUCTHUNT_API_TOKEN is not set") + } + const query = ` + query { + posts(first: 30, order: VOTES) { + edges { + node { + id + name + tagline + votesCount + url + slug + } + } + } + } + ` + + const response: any = await myFetch("https://api.producthunt.com/v2/api/graphql", { + method: "POST", + headers: { + "Authorization": token, + "Content-Type": "application/json", + "Accept": "application/json", + }, + body: JSON.stringify({ query }), + }) + const news: NewsItem[] = [] - $main.each((_, el) => { - const a = $(el).find("a").first() - const url = a.attr("href") - const title = $(el).find("a[data-test^=post-name]").text().replace(/^\d+\.\s*/, "") - const id = $(el).attr("data-test")?.replace("post-item-", "") - const vote = $(el).find("[data-test=vote-button]").text() - if (url && id && title) { + const posts = response?.data?.posts?.edges || [] + + for (const edge of posts) { + const post = edge.node + if (post.id && post.name) { news.push({ - url: `${baseURL}${url}`, - title, - id, + id: post.id, + title: post.name, + url: post.url || `https://www.producthunt.com/posts/${post.slug}`, extra: { - info: `△︎ ${vote}`, + info: ` △︎ ${post.votesCount || 0}`, + hover: post.tagline, }, }) } - }) + } + return news }) From 3b845ce6b5c115792b3d2f83aa15824b6539fa53 Mon Sep 17 00:00:00 2001 From: ourongxing Date: Mon, 27 Oct 2025 16:14:01 +0000 Subject: [PATCH 08/17] fix(source): mktnews --- server/sources/mktnews.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/server/sources/mktnews.ts b/server/sources/mktnews.ts index 148489e..b8034df 100644 --- a/server/sources/mktnews.ts +++ b/server/sources/mktnews.ts @@ -41,17 +41,21 @@ const flash = defineSource(async () => { const typeMap = { policy: "Policy", AI: "AI", financial: "Financial" } as const const allReports = categories.flatMap((category) => { - const flash_list = res.data.find(item => item.name === category)?.child[0]?.flash_list || [] - return flash_list.map(item => ({ ...item, type: typeMap[category] })) + const categoryData = res.data.find(item => item.name === category) + if (!categoryData?.child) return [] + + return categoryData.child.flatMap(subCategory => + (subCategory.flash_list || []).map(item => ({ ...item, type: typeMap[category] })), + ) }) return allReports .sort((a, b) => b.time.localeCompare(a.time)) .map(item => ({ id: item.id, - title: item.data.title || item.data.content, + title: item.data.title || item.data.content.match(/^【([^】]*)】(.*)$/)?.[1] || item.data.content, pubDate: item.time, - extra: { info: item.type }, + extra: { info: item.type, hover: item.data.content }, url: `https://mktnews.net/flashDetail.html?id=${item.id}`, })) }) From cb9b320996b86edb5a5082cd7ce024321f3092ef Mon Sep 17 00:00:00 2001 From: ourongxing Date: Mon, 27 Oct 2025 16:18:30 +0000 Subject: [PATCH 09/17] feat(docker): add PRODUCTHUNT_API_TOKEN environment variable --- docker-compose.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/docker-compose.yml b/docker-compose.yml index 2e5a82c..4fc6dbf 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -15,6 +15,7 @@ services: - JWT_SECRET= - INIT_TABLE=true - ENABLE_CACHE=true + - PRODUCTHUNT_API_TOKEN= volumes: newsnow_data: From 5a2e2a5e9cc52236c5df483bc29b024ac359ab39 Mon Sep 17 00:00:00 2001 From: ourongxing Date: Mon, 27 Oct 2025 16:20:57 +0000 Subject: [PATCH 10/17] chore: minor changes --- server/sources/producthunt.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/sources/producthunt.ts b/server/sources/producthunt.ts index 79ca023..8b5596a 100644 --- a/server/sources/producthunt.ts +++ b/server/sources/producthunt.ts @@ -1,10 +1,10 @@ import process from "node:process" import type { NewsItem } from "@shared/types" -const apiKey = process.env.PRODUCTHUNT_API_TOKEN -const token = `Bearer ${apiKey}` export default defineSource(async () => { - if (!apiKey) { + const apiToken = process.env.PRODUCTHUNT_API_TOKEN + const token = `Bearer ${apiToken}` + if (!apiToken) { throw new Error("PRODUCTHUNT_API_TOKEN is not set") } const query = ` From 8142074b3cf1387e87fc86726d1d5ce7502e2af4 Mon Sep 17 00:00:00 2001 From: ourongxing Date: Mon, 27 Oct 2025 16:25:24 +0000 Subject: [PATCH 11/17] chore: release v0.0.36 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7b1e80d..e8822e1 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "newsnow", "type": "module", - "version": "0.0.35", + "version": "0.0.36", "private": true, "packageManager": "pnpm@10.14.0+sha512.ad27a79641b49c3e481a16a805baa71817a04bbe06a38d17e60e2eaee83f6a146c6a688125f5792e48dd5ba30e7da52a5cda4c3992b9ccf333f9ce223af84748", "author": { From 3721fd383a2fc416e512a41e59c319250fc09864 Mon Sep 17 00:00:00 2001 From: ourongxing Date: Mon, 27 Oct 2025 16:58:16 +0000 Subject: [PATCH 12/17] feat(source): add steam --- public/icons/steam.png | Bin 0 -> 38554 bytes server/glob.d.ts | 1 + server/sources/steam.ts | 32 ++++++++++++++++++++++++++++++++ shared/pinyin.json | 3 ++- shared/pre-sources.ts | 8 ++++++++ shared/sources.json | 9 +++++++++ 6 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 public/icons/steam.png create mode 100644 server/sources/steam.ts diff --git a/public/icons/steam.png b/public/icons/steam.png new file mode 100644 index 0000000000000000000000000000000000000000..75ac308d379b7b2f0481c15fea742f657c6d5d3e GIT binary patch literal 38554 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 { + const response: any = await myFetch("https://store.steampowered.com/stats/stats/") + const $ = cheerio.load(response) + const $rows = $("#detailStats tr.player_count_row") + const news: NewsItem[] = [] + + $rows.each((_, el) => { + const $el = $(el) + const $a = $el.find("a.gameLink") + const url = $a.attr("href") + const gameName = $a.text().trim() + const currentPlayers = $el.find("td:first-child .currentServers").text().trim() + + if (url && gameName && currentPlayers) { + const title = gameName + news.push({ + url, + title, + id: url, + pubDate: Date.now(), + extra: { + info: currentPlayers, + }, + }) + } + }) + + return news +}) diff --git a/shared/pinyin.json b/shared/pinyin.json index b1d2316..e1a7bc0 100644 --- a/shared/pinyin.json +++ b/shared/pinyin.json @@ -42,5 +42,6 @@ "ifeng": "fenghuangwang-redianzixun", "chongbuluo-latest": "chongbuluo-zuixin", "chongbuluo-hot": "chongbuluo-zuire", - "douban": "douban-remendianying" + "douban": "douban-remendianying", + "steam": "Steam-zaixianrenshu" } \ No newline at end of file diff --git a/shared/pre-sources.ts b/shared/pre-sources.ts index 61d55a3..c19f08a 100644 --- a/shared/pre-sources.ts +++ b/shared/pre-sources.ts @@ -421,6 +421,14 @@ export const originSources = { type: "hottest", home: "https://www.douban.com", }, + "steam": { + name: "Steam", + column: "world", + title: "在线人数", + color: "blue", + type: "hottest", + home: "https://store.steampowered.com", + }, } as const satisfies Record export function genSources() { diff --git a/shared/sources.json b/shared/sources.json index 01bb44e..56c360c 100644 --- a/shared/sources.json +++ b/shared/sources.json @@ -481,5 +481,14 @@ "home": "https://www.douban.com", "color": "green", "interval": 600000 + }, + "steam": { + "title": "在线人数", + "name": "Steam", + "type": "hottest", + "column": "world", + "home": "https://store.steampowered.com", + "color": "blue", + "interval": 600000 } } \ No newline at end of file From 3e870e1e37e863afc347d8a2baec973cb7fc290e Mon Sep 17 00:00:00 2001 From: ourongxing Date: Sat, 1 Nov 2025 10:09:07 +0000 Subject: [PATCH 13/17] chore: remove autorefresh script --- .github/workflows/auto-refresh.yml | 23 ----------------------- scripts/refresh.ts | 5 ----- 2 files changed, 28 deletions(-) delete mode 100644 .github/workflows/auto-refresh.yml delete mode 100644 scripts/refresh.ts diff --git a/.github/workflows/auto-refresh.yml b/.github/workflows/auto-refresh.yml deleted file mode 100644 index 0bd48e5..0000000 --- a/.github/workflows/auto-refresh.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: Auto Refresh - -on: - schedule: - - cron: '*/20 0-17,22,23 * * *' - workflow_dispatch: - -jobs: - release: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - uses: actions/setup-node@v4 - with: - node-version: lts/* - - - name: Refresh - env: - JWT_TOKEN: ${{ secrets.JWT_TOKEN }} - run: npx tsx ./scripts/refresh.ts diff --git a/scripts/refresh.ts b/scripts/refresh.ts deleted file mode 100644 index 8e6c21f..0000000 --- a/scripts/refresh.ts +++ /dev/null @@ -1,5 +0,0 @@ -import sources from "../shared/sources.json" - -Promise.all(Object.keys(sources).map(id => - fetch(`https://newsnow.busiyi.world/api/s?id=${id}`), -)).catch(console.error) From b60bb219ec9a5131ae7c531e580996d3524fabac Mon Sep 17 00:00:00 2001 From: likanug <14996214+bruceblink@users.noreply.github.com> Date: Thu, 20 Nov 2025 00:28:55 +0800 Subject: [PATCH 14/17] =?UTF-8?q?feat:=20Add=20new=20source:=20=E8=85=BE?= =?UTF-8?q?=E8=AE=AF=E6=96=B0=E9=97=BB-=E7=BB=BC=E5=90=88=E6=97=A9?= =?UTF-8?q?=E6=8A=A5=20(#255)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/icons/tencent.png | Bin 0 -> 3446 bytes server/glob.d.ts | 1 + server/sources/tencent.ts | 63 ++++++++++++++++++++++++++++++++++++++ shared/pinyin.json | 3 +- shared/pre-sources.ts | 14 +++++++++ shared/sources.json | 19 ++++++++++++ 6 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 public/icons/tencent.png create mode 100644 server/sources/tencent.ts diff --git a/public/icons/tencent.png b/public/icons/tencent.png new file mode 100644 index 0000000000000000000000000000000000000000..67c9e121e761cb7645c60c722b227c1eee426481 GIT binary patch literal 3446 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 literal 0 HcmV?d00001 diff --git a/server/glob.d.ts b/server/glob.d.ts index a2bb8bd..f000c4c 100644 --- a/server/glob.d.ts +++ b/server/glob.d.ts @@ -32,6 +32,7 @@ declare module 'glob:./sources/{*.ts,**/index.ts}' { export const sputniknewscn: typeof import('./sources/sputniknewscn') export const sspai: typeof import('./sources/sspai') export const steam: typeof import('./sources/steam') + export const tencent: typeof import('./sources/tencent') export const thepaper: typeof import('./sources/thepaper') export const tieba: typeof import('./sources/tieba') export const toutiao: typeof import('./sources/toutiao') diff --git a/server/sources/tencent.ts b/server/sources/tencent.ts new file mode 100644 index 0000000..8fe72c9 --- /dev/null +++ b/server/sources/tencent.ts @@ -0,0 +1,63 @@ +import { myFetch } from "#/utils/fetch" +import { defineSource } from "#/utils/source" + +interface WapRes { + ret: number + msg: string + data: { + id: number + name: string + lead: string + cover?: string + shareTitle: string + shareAbstract: string + sharePic: string + is724: boolean + is724Paper: boolean + head_cmsid: string + feed_style: number + head_article: { + live_info: string + title: string + img: string + pub_time: string + media_name: string + } + paperInfo: any + tabs: { + id: string + channel_id: string + name: string + source: string + type: string + articleList: any[] + article_count: number + sub_tab: string + }[] + banner: string + } +} + +/** + * 综合早报 + */ +const comprehensiveNews = defineSource(async () => { + const url = "https://i.news.qq.com/web_backend/v2/getTagInfo?tagId=aEWqxLtdgmQ%3D" + const res = await myFetch(url, { + headers: { + Referer: "https://news.qq.com/", + }, + }) + return res.data.tabs[0].articleList.map(news => ({ + id: news.id, + title: news.title, + url: news.link_info.url, + extra: { + hover: news.desc, + }, + })) +}) + +export default defineSource({ + "tencent-hot": comprehensiveNews, +}) diff --git a/shared/pinyin.json b/shared/pinyin.json index e1a7bc0..23d1778 100644 --- a/shared/pinyin.json +++ b/shared/pinyin.json @@ -43,5 +43,6 @@ "chongbuluo-latest": "chongbuluo-zuixin", "chongbuluo-hot": "chongbuluo-zuire", "douban": "douban-remendianying", - "steam": "Steam-zaixianrenshu" + "steam": "Steam-zaixianrenshu", + "tencent-hot": "tengxunxinwen-zonghezaobao" } \ No newline at end of file diff --git a/shared/pre-sources.ts b/shared/pre-sources.ts index c19f08a..551311f 100644 --- a/shared/pre-sources.ts +++ b/shared/pre-sources.ts @@ -429,6 +429,20 @@ export const originSources = { type: "hottest", home: "https://store.steampowered.com", }, + "tencent": { + name: "腾讯新闻", + column: "china", + color: "blue", + home: "https://news.qq.com", + sub: { + hot: { + title: "综合早报", + type: "hottest", + interval: Time.Common, + home: "https://news.qq.com/tag/aEWqxLtdgmQ=", + }, + }, + }, } as const satisfies Record export function genSources() { diff --git a/shared/sources.json b/shared/sources.json index 56c360c..ded718a 100644 --- a/shared/sources.json +++ b/shared/sources.json @@ -490,5 +490,24 @@ "home": "https://store.steampowered.com", "color": "blue", "interval": 600000 + }, + "tencent": { + "redirect": "tencent-hot", + "name": "腾讯新闻", + "type": "hottest", + "column": "china", + "home": "https://news.qq.com/tag/aEWqxLtdgmQ=", + "color": "blue", + "interval": 1800000, + "title": "综合早报" + }, + "tencent-hot": { + "name": "腾讯新闻", + "type": "hottest", + "column": "china", + "home": "https://news.qq.com/tag/aEWqxLtdgmQ=", + "color": "blue", + "interval": 1800000, + "title": "综合早报" } } \ No newline at end of file From 7e88e142b2067c0bf421d2746819bdc5de919413 Mon Sep 17 00:00:00 2001 From: ourongxing Date: Thu, 20 Nov 2025 09:59:51 +0000 Subject: [PATCH 15/17] fix: weibo --- server/sources/weibo.ts | 186 ++++++++++------------------------------ 1 file changed, 44 insertions(+), 142 deletions(-) diff --git a/server/sources/weibo.ts b/server/sources/weibo.ts index 878b183..52b5a01 100644 --- a/server/sources/weibo.ts +++ b/server/sources/weibo.ts @@ -1,150 +1,52 @@ -export interface Root { - ok: number - data: Data -} - -export interface Data { - mapi: any[] - cards: Card[] - cardlistInfo: CardlistInfo - scheme: string - showAppTips: number -} - -export interface Card { - card_group: CardGroup[] - card_type: number - show_type: number - itemid?: string - title?: string -} - -export interface CardGroup { - actionlog?: Actionlog - card_type: number - pic?: string - itemid?: string - icon?: string - icon_width?: number - icon_height?: number - desc?: string - scheme: string - desc_extr: any - promotion?: Promotion - display_arrow?: number - show_type?: number - title?: string - is_show_arrow?: number - left_tag_img?: string - sub_title?: string -} - -export interface Actionlog { - luicode: string - lfid: string - uicode: string - act_code: number - act_type: number - fid: string - ext: string -} - -export interface Promotion { - monitor_url: MonitorUrl[] -} - -export interface MonitorUrl { - third_party_click: string - third_party_show: string - type: string - monitor_name?: string -} - -export interface CardlistInfo { - select_id: string - title_top: string - show_style: number - starttime: number - can_shared: number - v_p: string - containerid: string - page_type: string - nick: string - cardlist_head_cards: CardlistHeadCard[] - enable_load_imge_scrolling: number - page_title: string - search_request_id: string - load_more_threshold: number - pagesize: number - page_common_ext: string - cardlist_menus: any[] - total: number - headbg_animation: string - page_size: number - page: any -} - -export interface CardlistHeadCard { - title_top?: string - show_menu: boolean - head_type_name: string - head_type: number - head_data?: HeadData - channel_list?: ChannelList[] -} - -export interface HeadData { - cover_url: string - show_navi_mask: boolean - show_title: boolean - data_type: number - scheme: string -} - -export interface ChannelList { - actionlog: Actionlog2 - scheme: string - containerid: string - name: string - default_add: number - id: number - must_show: number - replaced_name?: string -} - -export interface Actionlog2 { - luicode: string - lfid: string - uicode: string - act_code: number - act_type: number - fid: string - ext: string -} +import * as cheerio from "cheerio" export default defineSource(async () => { - const url = "https://m.weibo.cn/api/container/getIndex?containerid=106003type%3D25%26t%3D3%26disable_hot%3D1%26filter_type%3Drealtimehot&title=%E5%BE%AE%E5%8D%9A%E7%83%AD%E6%90%9C&extparam=filter_type%3Drealtimehot%26mi_cid%3D100103%26pos%3D0_0%26c_type%3D30%26display_time%3D1540538388&luicode=10000011&lfid=231583" - const res: Root = await myFetch(url, { + const baseurl = "https://s.weibo.com" + const url = `${baseurl}/top/summary?cate=realtimehot` + + const html = await myFetch(url, { headers: { - "referer": "https://s.weibo.com/top/summary?cate=realtimehot", - "mweibo-pwa": "1", - "x-requested-with": "XMLHttpRequest", + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36", + // https://github.com/v5tech/weibo-trending-hot-search + "Cookie": "SUB=_2AkMWIuNSf8NxqwJRmP8dy2rhaoV2ygrEieKgfhKJJRMxHRl-yT9jqk86tRB6PaLNvQZR6zYUcYVT1zSjoSreQHidcUq7", + "referer": url, }, }) - return res.data.cards[0].card_group - .filter((k, i) => i !== 0 && k.desc && !k.actionlog?.ext.includes("ads_word")) - .map((k) => { - return { - id: k.desc!, - title: k.desc!, - extra: { - icon: k.icon && { - url: proxyPicture(k.icon), - scale: 1.5, + + const $ = cheerio.load(html) + + const rows = $("#pl_top_realtimehot table tbody tr").slice(1) + + const hotNews: NewsItem[] = [] + + rows.each((_, row) => { + const $row = $(row) + const $link = $row.find("td.td-02 a").filter((_, el) => { + const href = $(el).attr("href") + return !!(href && !href.includes("javascript:void(0);")) + }).first() + + if ($link.length) { + const title = $link.text().trim() + const href = $link.attr("href") + + if (title && href) { + const $flag = $row.find("td.td-03").text().trim() + const flagUrl = { + 新: "https://simg.s.weibo.com/moter/flags/1_0.png", + 热: "https://simg.s.weibo.com/moter/flags/2_0.png", + }[$flag] + hotNews.push({ + id: title, + title, + url: `${baseurl}${href}`, + mobileUrl: `${baseurl}${href}`, + extra: { + icon: flagUrl ? { url: proxyPicture(flagUrl), scale: 1.5 } : undefined, }, - }, - url: `https://s.weibo.com/weibo?q=${encodeURIComponent(`#${k.desc}#`)}`, - mobileUrl: k.scheme, + }) } - }) + } + }) + return hotNews }) From fa9f552d73924d298f6faf6e888801614ef84d08 Mon Sep 17 00:00:00 2001 From: ourongxing Date: Thu, 20 Nov 2025 10:06:54 +0000 Subject: [PATCH 16/17] fix: kaopu source --- server/sources/kaopu.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/server/sources/kaopu.ts b/server/sources/kaopu.ts index 41a9178..ef0c141 100644 --- a/server/sources/kaopu.ts +++ b/server/sources/kaopu.ts @@ -2,17 +2,17 @@ type Res = { description: string link: string // Date - pubDate: string + pub_date: string publisher: string title: string }[] export default defineSource(async () => { - const res = await Promise.all(["https://kaopustorage.blob.core.windows.net/jsondata/news_list_beta_hans_0.json", "https://kaopustorage.blob.core.windows.net/jsondata/news_list_beta_hans_1.json"].map(url => myFetch(url) as Promise)) - return res.flat().filter(k => ["财新", "公视"].every(h => k.publisher !== h)).map((k) => { + const res: Res = await $fetch("https://kaopustorage.blob.core.windows.net/news-prod/news_list_hans_0.json") + return res.filter(k => ["财新", "公视"].every(h => k.publisher !== h)).map((k) => { return { id: k.link, title: k.title, - pubDate: k.pubDate, + pubDate: k.pub_date, extra: { hover: k.description, info: k.publisher, From fcdf8374356e706412fdaaa93cd608b7f3af2091 Mon Sep 17 00:00:00 2001 From: ourongxing Date: Thu, 20 Nov 2025 10:14:46 +0000 Subject: [PATCH 17/17] chore: release v0.0.37 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e8822e1..4bba3f1 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "newsnow", "type": "module", - "version": "0.0.36", + "version": "0.0.37", "private": true, "packageManager": "pnpm@10.14.0+sha512.ad27a79641b49c3e481a16a805baa71817a04bbe06a38d17e60e2eaee83f6a146c6a688125f5792e48dd5ba30e7da52a5cda4c3992b9ccf333f9ce223af84748", "author": {