Skip to content

Commit dc32d68

Browse files
authored
fix(blizzard): 新闻路由报错不能使用 (#17956)
* fix(blizzard): 新闻路由报错不能使用 * fix(blizzard): 修改 cache key
1 parent d525693 commit dc32d68

File tree

1 file changed

+120
-31
lines changed

1 file changed

+120
-31
lines changed

lib/routes/blizzard/news.ts

Lines changed: 120 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,15 @@ export const route: Route = {
2727
| Diablo II: Resurrected | diablo2 |
2828
| Diablo III | diablo3 |
2929
| Diablo IV | diablo4 |
30-
| Diablo: Immortal | diablo-immortal |
30+
| Diablo Immortal | diablo-immortal |
3131
| Hearthstone | hearthstone |
3232
| Heroes of the Storm | heroes-of-the-storm |
3333
| Overwatch 2 | overwatch |
3434
| StarCraft: Remastered | starcraft |
3535
| StarCraft II | starcraft2 |
3636
| World of Warcraft | world-of-warcraft |
37-
| Warcraft III: Reforged | warcraft3 |
37+
| Warcraft 3: Reforged | warcraft3 |
38+
| Warcraft Rumble | warcraft-rumble |
3839
| Battle.net | battlenet |
3940
| BlizzCon | blizzcon |
4041
| Inside Blizzard | blizzard |
@@ -59,49 +60,137 @@ export const route: Route = {
5960
| 繁體中文 | zh-tw |`,
6061
};
6162

63+
const GAME_MAP = {
64+
diablo2: {
65+
key: 'diablo2',
66+
value: 'diablo-2-resurrected',
67+
id: 'blt54fbd3787a705054',
68+
},
69+
diablo3: {
70+
key: 'diablo3',
71+
value: 'diablo-3',
72+
id: 'blt2031aef34200656d',
73+
},
74+
diablo4: {
75+
key: 'diablo4',
76+
value: 'diablo-4',
77+
id: 'blt795c314400d7ded9',
78+
},
79+
'diablo-immortal': {
80+
key: 'diablo-immortal',
81+
value: 'diablo-immortal',
82+
id: 'blt525c436e4a1b0a97',
83+
},
84+
hearthstone: {
85+
key: 'hearthstone',
86+
value: 'hearthstone',
87+
id: 'blt5cfc6affa3ca0638',
88+
},
89+
'heroes-of-the-storm': {
90+
key: 'heroes-of-the-storm',
91+
value: 'heroes-of-the-storm',
92+
id: 'blt2e50e1521bb84dc6',
93+
},
94+
overwatch: {
95+
key: 'overwatch',
96+
value: 'overwatch',
97+
id: 'blt376fb94931906b6f',
98+
},
99+
starcraft: {
100+
key: 'starcraft',
101+
value: 'starcraft',
102+
id: 'blt81d46fcb05ab8811',
103+
},
104+
starcraft2: {
105+
key: 'starcraft2',
106+
value: 'starcraft-2',
107+
id: 'bltede2389c0a8885aa',
108+
},
109+
'world-of-warcraft': {
110+
key: 'world-of-warcraft',
111+
value: 'world-of-warcraft',
112+
id: 'blt2caca37e42f19839',
113+
},
114+
warcraft3: {
115+
key: 'warcraft3',
116+
value: 'warcraft-3',
117+
id: 'blt24859ba8086fb294',
118+
},
119+
'warcraft-rumble': {
120+
key: 'warcraft-rumble',
121+
value: 'warcraft-rumble',
122+
id: 'blte27d02816a8ff3e1',
123+
},
124+
battlenet: {
125+
key: 'battlenet',
126+
value: 'battle-net',
127+
id: 'blt90855744d00cd378',
128+
},
129+
blizzcon: {
130+
key: 'blizzcon',
131+
value: 'blizzcon',
132+
id: 'bltec70ad0ea4fd6d1d',
133+
},
134+
blizzard: {
135+
key: 'blizzard',
136+
value: 'blizzard',
137+
id: 'blt500c1f8b5470bfdb',
138+
},
139+
};
140+
141+
function getSearchParams(category = 'all') {
142+
return category === 'all'
143+
? Object.values(GAME_MAP)
144+
.map((item) => `feedCxpProductIds[]=${item.id}`)
145+
.join('&')
146+
: `feedCxpProductIds[]=${GAME_MAP[category].id}`;
147+
}
148+
62149
async function handler(ctx) {
63-
const category = ctx.req.param('category') || '';
150+
const category = GAME_MAP[ctx.req.param('category')]?.key || 'all';
64151
const language = ctx.req.param('language') || 'en-us';
152+
const rootUrl = `https://news.blizzard.com/${language}`;
153+
const currentUrl = category === 'all' ? rootUrl : `${rootUrl}/?filter=${GAME_MAP[category].value}`;
154+
const apiUrl = `${rootUrl}/api/news/blizzard`;
155+
let rssTitle = '';
65156

66-
const rootUrl = 'https://news.blizzard.com';
67-
const currentUrl = `${rootUrl}/${language}/${category}`;
68-
const apiUrl = `${rootUrl}/${language}/blog/list`;
69-
const response = await got(apiUrl, {
70-
searchParams: {
71-
community: category === '' ? 'all' : category,
157+
const {
158+
data: {
159+
feed: { contentItems: response },
72160
},
73-
});
74-
75-
const $ = load(response.data.html, null, false);
161+
} = await got(`${apiUrl}?${getSearchParams(category)}`);
76162

77-
const list = $('.FeaturedArticle-text > a, .ArticleListItem > article > a')
78-
.slice(0, ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit'), 10) : 30)
79-
.toArray()
80-
.map((item) => {
81-
item = $(item);
82-
return {
83-
title: item.text(),
84-
link: `${rootUrl}${item.attr('href')}`,
85-
};
86-
});
163+
const list = response.map((item) => {
164+
const content = item.properties;
165+
rssTitle = category === 'all' ? 'All News' : content.cxpProduct.title; // 这个是用来填充 RSS 订阅源频道级别 title,没别的地方能拿到了(而且会根据语言切换)
166+
return {
167+
title: content.title,
168+
link: content.newsUrl,
169+
author: content.author,
170+
category: content.category,
171+
guid: content.newsId,
172+
description: content.summary,
173+
pubDate: content.lastUpdated,
174+
};
175+
});
87176

88177
const items = await Promise.all(
89178
list.map((item) =>
90179
cache.tryGet(item.link, async () => {
91-
const detailResponse = await got(item.link);
92-
const content = load(detailResponse.data);
93-
94-
item.author = content('.ArticleDetail-bylineAuthor').text();
95-
item.description = content('.ArticleDetail-headingImageBlock').html() + content('.ArticleDetail-content').html();
96-
item.pubDate = content('.ArticleDetail-subHeadingLeft time').attr('timestamp');
97-
98-
return item;
180+
try {
181+
const { data: response } = await got(item.link);
182+
const $ = load(response);
183+
item.description = $('.Content').html();
184+
return item;
185+
} catch {
186+
return item;
187+
}
99188
})
100189
)
101190
);
102191

103192
return {
104-
title: $('title').text(),
193+
title: rssTitle,
105194
link: currentUrl,
106195
item: items,
107196
};

0 commit comments

Comments
 (0)