fix(route/cls): fix telegraph api (#22171)

This commit is contained in:
Tony 2026-06-03 11:45:31 +08:00 committed by GitHub
parent 7931a8d4ce
commit 8eaa2e06f9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 48 additions and 56 deletions

View File

@ -3,7 +3,7 @@ import { load } from 'cheerio';
import InvalidParameterError from '@/errors/types/invalid-parameter';
import type { Route } from '@/types';
import cache from '@/utils/cache';
import got from '@/utils/got';
import ofetch from '@/utils/ofetch';
import { parseDate } from '@/utils/parse-date';
import { renderDepthDescription } from './templates/depth';
@ -61,31 +61,28 @@ async function handler(ctx) {
const apiUrl = `${rootUrl}/v3/depth/home/assembled/${category}`;
const currentUrl = `${rootUrl}/depth?id=${category}`;
const response = await got({
method: 'get',
url: apiUrl,
searchParams: getSearchParams(),
const response = await ofetch(apiUrl, {
query: getSearchParams(),
});
let items = [...response.data.data.top_article, ...response.data.data.depth_list].slice(0, limit).map((item) => ({
let items = [...response.data.top_article, ...response.data.depth_list].slice(0, limit).map((item) => ({
title: item.title || item.brief,
link: `${rootUrl}/detail/${item.id}`,
pubDate: parseDate(item.ctime * 1000),
pubDate: parseDate(item.ctime, 'X'),
author: item.source,
category: item.article_tag?.map((tag) => tag.name),
image: item.image,
}));
items = await Promise.all(
items.map((item) =>
cache.tryGet(item.link, async () => {
const detailResponse = await got({
method: 'get',
url: item.link,
});
const detailResponse = await ofetch(item.link);
const content = load(detailResponse.data);
const content = load(detailResponse);
const nextData = JSON.parse(content('script#__NEXT_DATA__').text());
const articleDetail = nextData.props.initialState.detail.articleDetail;
const articleDetail = nextData.props.pageProps.articleDetail;
item.author = articleDetail.author?.name ?? item.author ?? '';
item.description = renderDepthDescription(articleDetail);

View File

@ -2,7 +2,7 @@ import { load } from 'cheerio';
import type { Route } from '@/types';
import cache from '@/utils/cache';
import got from '@/utils/got';
import ofetch from '@/utils/ofetch';
import { parseDate } from '@/utils/parse-date';
import { renderDepthDescription } from './templates/depth';
@ -37,30 +37,26 @@ async function handler(ctx) {
const apiUrl = `${rootUrl}/v2/article/hot/list`;
const response = await got({
method: 'get',
url: apiUrl,
searchParams: getSearchParams(),
const response = await ofetch(apiUrl, {
query: getSearchParams(),
});
let items = response.data.data.slice(0, limit).map((item) => ({
let items = response.data.slice(0, limit).map((item) => ({
title: item.title || item.brief,
link: `${rootUrl}/detail/${item.id}`,
pubDate: parseDate(item.ctime * 1000),
pubDate: parseDate(item.ctime, 'X'),
author: item.author,
}));
items = await Promise.all(
items.map((item) =>
cache.tryGet(item.link, async () => {
const detailResponse = await got({
method: 'get',
url: item.link,
});
const detailResponse = await ofetch(item.link);
const content = load(detailResponse.data);
const content = load(detailResponse);
const nextData = JSON.parse(content('script#__NEXT_DATA__').text());
const articleDetail = nextData.props.initialState.detail.articleDetail;
const articleDetail = nextData.props.pageProps.articleDetail;
item.author = articleDetail.author?.name ?? item.author ?? '';
item.description = renderDepthDescription(articleDetail);

View File

@ -2,7 +2,7 @@ import { load } from 'cheerio';
import type { Route } from '@/types';
import cache from '@/utils/cache';
import got from '@/utils/got';
import ofetch from '@/utils/ofetch';
import { parseDate } from '@/utils/parse-date';
import { renderDescription } from './templates/description';
@ -15,8 +15,8 @@ export const handler = async (ctx) => {
const currentUrl = new URL(`subject/${id}`, rootUrl).href;
const apiUrl = new URL(`api/subject/${id}/article`, rootUrl).href;
const { data: response } = await got(apiUrl, {
searchParams: getSearchParams({
const response = await ofetch(apiUrl, {
query: getSearchParams({
Subject_Id: id,
}),
});
@ -50,11 +50,11 @@ export const handler = async (ctx) => {
items = await Promise.all(
items.map((item) =>
cache.tryGet(item.link, async () => {
const { data: detailResponse } = await got(item.link);
const detailResponse = await ofetch(item.link);
const $$ = load(detailResponse);
const data = JSON.parse($$('script#__NEXT_DATA__').text())?.props?.initialState?.detail?.articleDetail ?? undefined;
const data = JSON.parse($$('script#__NEXT_DATA__').text())?.props?.pageProps?.articleDetail ?? undefined;
if (!data) {
return item;
@ -62,7 +62,7 @@ export const handler = async (ctx) => {
const title = data.title;
const description = renderDescription({
images: data.images.map((i) => ({
images: data.images?.map((i) => ({
src: i,
alt: title,
})),
@ -94,11 +94,11 @@ export const handler = async (ctx) => {
)
);
const { data: currentResponse } = await got(currentUrl);
const currentResponse = await ofetch(currentUrl);
const $ = load(currentResponse);
const data = JSON.parse($('script#__NEXT_DATA__').text())?.props?.initialProps?.pageProps?.subjectDetail ?? undefined;
const data = JSON.parse($('script#__NEXT_DATA__').text())?.props?.pageProps?.data ?? undefined;
const author = '财联社';
const image = data?.img ?? undefined;

View File

@ -1,7 +1,8 @@
import type { Context } from 'hono';
import { renderToString } from 'hono/jsx/dom/server';
import type { Route } from '@/types';
import got from '@/utils/got';
import ofetch from '@/utils/ofetch';
import { parseDate } from '@/utils/parse-date';
import { getSearchParams, rootUrl } from './utils';
@ -9,12 +10,11 @@ import { getSearchParams, rootUrl } from './utils';
const categories = {
watch: '看盘',
announcement: '公司',
explain: '解读',
red: '加红',
jpush: '推送',
remind: '提醒',
fund: '基金',
hk: '港股',
hk_us: '港美股',
};
const renderTelegraphDescription = (item) =>
@ -55,41 +55,39 @@ export const route: Route = {
maintainers: ['nczitzk'],
handler,
url: 'cls.cn/telegraph',
description: `| 看盘 | 公司 | 解读 | 加红 | 推送 | 提醒 | 基金 | 港股 |
| ----- | ------------ | ------- | ---- | ----- | ------ | ---- | ---- |
| watch | announcement | explain | red | jpush | remind | fund | hk |`,
description: `| 看盘 | 公司 | 加红 | 提醒 | 基金 | 港股 |
| ----- | ------------ | ---- | ------ | ---- | ------ |
| watch | announcement | red | remind | fund | hk\\_us |`,
};
async function handler(ctx) {
const category = ctx.req.param('category') ?? '';
const limit = ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit')) : 50;
async function handler(ctx: Context) {
const category = ctx.req.param('category');
const limit = ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit')!) : 50;
let apiUrl = `${rootUrl}/nodeapi/updateTelegraphList`;
let apiUrl = `${rootUrl}/api/cache`;
if (category) {
apiUrl = `${rootUrl}/v1/roll/get_roll_list`;
}
const currentUrl = `${rootUrl}/telegraph`;
const response = await got({
method: 'get',
url: apiUrl,
searchParams: getSearchParams({
const response = await ofetch(apiUrl, {
query: getSearchParams({
category,
hasFirstVipArticle: 1,
name: category ? undefined : 'telegraph',
}),
});
const items = response.data.data.roll_data.slice(0, limit).map((item) => ({
const items = response.data.roll_data.slice(0, limit).map((item) => ({
title: item.title || item.content,
link: item.shareurl,
description: renderTelegraphDescription(item),
pubDate: parseDate(item.ctime * 1000),
pubDate: parseDate(item.ctime, 'X'),
category: item.subjects?.map((s) => s.subject_name),
}));
return {
title: `财联社 - 电报${category === '' ? '' : ` - ${categories[category]}`}`,
title: `财联社 - 电报${category ? ` - ${categories[category]}` : ''}`,
link: currentUrl,
item: items,
};

View File

@ -5,14 +5,15 @@ const rootUrl = 'https://www.cls.cn';
const params = {
appName: 'CailianpressWeb',
os: 'web',
sv: '7.7.5',
sv: '8.7.9',
};
const getSearchParams = (moreParams) => {
const searchParams = new URLSearchParams({ ...params, ...moreParams });
const getSearchParams = (moreParams?) => {
const filtered = Object.fromEntries(Object.entries({ ...params, ...moreParams }).filter(([_, v]) => v !== undefined));
const searchParams = new URLSearchParams(filtered as Record<string, string>);
searchParams.sort();
searchParams.append('sign', CryptoJS.MD5(CryptoJS.SHA1(searchParams.toString()).toString()).toString());
return searchParams;
return Object.fromEntries(searchParams);
};
export { getSearchParams, rootUrl };