feat(route): Fix and update LoveLive! Series News (#16936)

* Fix and update LoveLive NEWS route

* Radar support

* Update Date parse

* Remove unnecessary escape characters

* Modify route name

* Use API to fetch articles

* fix: schedule

---------
This commit is contained in:
Zhaowei Zhong 2024-09-27 23:48:32 +09:00 committed by GitHub
parent 9ea1248341
commit 3bb7b35043
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 77 additions and 36 deletions

View File

@ -1,6 +1,6 @@
import type { Namespace } from '@/types';
export const namespace: Namespace = {
name: 'lovelive-anime',
name: 'Love Live! Official Website',
url: 'www.lovelive-anime.jp',
};

View File

@ -7,13 +7,20 @@ import got from '@/utils/got';
import { load } from 'cheerio';
import path from 'node:path';
import { art } from '@/utils/render';
import ofetch from '@/utils/ofetch';
import timezone from '@/utils/timezone';
import { parseDate } from '@/utils/parse-date';
const renderDescription = (desc) => art(path.join(__dirname, 'templates/description.art'), desc);
export const route: Route = {
path: '/news/:option?',
path: '/news/:abbr?/:category?/:option?',
categories: ['anime'],
example: '/lovelive-anime/news',
parameters: { option: 'Crawl full text when `option` is `detail`.' },
parameters: {
abbr: 'The path to the Love Live series of sub-projects on the official website is detailed in the table below, `abbr` is `detail` when crawling the full text',
category: 'The official website lists the Topics category, `category` is `detail` when crawling the full text, other categories see the following table for details',
option: 'Crawl full text when `option` is `detail`.',
},
features: {
requireConfig: false,
requirePuppeteer: false,
@ -24,45 +31,68 @@ export const route: Route = {
},
radar: [
{
source: ['www.lovelive-anime.jp/', 'www.lovelive-anime.jp/news'],
source: ['www.lovelive-anime.jp/', 'www.lovelive-anime.jp/news/'],
target: '/news',
},
],
name: 'Love Live! Official Website Latest NEWS',
maintainers: ['axojhf'],
name: 'News',
maintainers: ['axojhf', 'zhaoweizhong'],
handler,
url: 'www.lovelive-anime.jp/',
description: `| Sub-project Name | All Projects | Lovelive! | Lovelive! Sunshine!! | Lovelive! Nijigasaki High School Idol Club | Lovelive! Superstar!! | 蓮ノ空女学院 | 幻日のヨハネ | ラブライブ!スクールアイドルミュージカル |
| -------------------------------- | -------------- | ----------- | -------------------- | ------------------------------------------ | --------------------- | ------------ | ------------ | ---------------------------------------- |
| \`abbr\`parameter | <u>*No parameter*</u> | lovelive | sunshine | nijigasaki | superstar | hasunosora | yohane | musical |
| Category Name | | | | | | / | / | / | | | | | | | |
| ------------------- | --------------------- | -------- | -------------- | ---------------- | ------- | ----------------- | --------------------- | ----------------- | ------ | ------ | ------ | -------- | ---------- | ------ | ------------ |
| \`category\`parameter | <u>*No parameter*</u> | music | anime_movie | cast_movie | theater | onair | radio | event | books | goods | game | media | local | campaign | other |`,
};
async function handler(ctx) {
const rootUrl = 'https://www.lovelive-anime.jp/news/';
const abbr = ctx.req.param('abbr');
const category = ctx.req.param('category');
const option = ctx.req.param('option');
const response = await got(rootUrl);
const isDetail = abbr === 'detail' || category === 'detail' || option === 'detail';
let series = '';
let subcategory = '';
const $ = load(response.data);
if (abbr && abbr !== 'detail') {
series = abbr;
if (category && category !== 'detail') {
subcategory = category;
}
}
const pageFace = $('div.c-card.p-colum__box')
.map((_, item) => {
item = $(item);
const limit = 20;
return {
link: item.find('a.c-card__head').attr('href'),
pubDate: item.find('span.c-card__date').text(),
title: item.find('div.c-card__title').text(),
// description: `${item.find('div.c-card__title').text()}<br><img src="${item.find('a.c-card__head > div > figure > img').attr('src')}">`
description: renderDescription({
title: item.find('div.c-card__title').text(),
imglink: item.find('a.c-card__head > div > figure > img').attr('src'),
}),
};
})
.get();
let url = `https://www.lovelive-anime.jp/common/api/article_list.php?site=jp&ip=lovelive&limit=${limit}&data=`;
const params: { category: string[]; series?: string[]; subcategory?: string[] } = { category: ['NEWS'] };
if (series) {
params.series = [series];
}
if (subcategory) {
params.subcategory = [subcategory];
}
url += encodeURIComponent(JSON.stringify(params));
let items = pageFace;
const data = await ofetch(url);
if (ctx.req.param('option') === 'detail') {
const articles = data.data.article_list.map((item) => ({
title: item.title,
link: item.url,
description: renderDescription({
imglink: 'https://www.lovelive-anime.jp' + item.thumbnail,
}),
pubDate: timezone(parseDate(item.dspdate), +9),
category: item.categories.subcategory.map((category) => category.name),
}));
let items = articles;
if (isDetail) {
items = await Promise.all(
pageFace.map((item) =>
articles.map((item) =>
cache.tryGet(item.link, async () => {
const detailResp = await got(item.link);
const $ = load(detailResp.data);

View File

@ -9,20 +9,33 @@ const renderDescription = (desc) => art(path.join(__dirname, 'templates/schedule
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import timezone from 'dayjs/plugin/timezone';
dayjs.extend(utc);
dayjs.extend(timezone);
export const route: Route = {
path: '/schedules/:serie?/:category?',
name: 'Unknown',
maintainers: [],
parameters: {
serie: 'Love Live! Series sub-projects abbreviation, see the following table',
category: 'The official website lists the categories, see the following table for details',
},
name: 'Schedule',
example: '/lovelive-anime/schedules',
categories: ['anime'],
maintainers: ['axojhf'],
handler,
description: `| Sub-project Name (not full name) | 全シリーズ | Lovelive! | Lovelive! Sunshine!! | Lovelive! Nijigasaki High School Idol Club | Lovelive! Superstar!! | ラブライブ!スクールアイドルミュージカル |
| -------------------------------- | ----------------------- | ---------- | -------------------- | ------------------------------------------ | --------------------- | ---------------------------------------- |
| \`serie\` parameter | *No parameter* or \`all\` | \`lovelive\` | \`sunshine\` | \`nijigasaki\` | \`superstar\` | \`musical\` |
| Category Name | | | | |
| -------------------- | ----------------------- | ------ | -------- | --------- |
| \`category\` parameter | *No parameter* or \`all\` | \`live\` | \`event\` | \`haishin\` |`,
};
async function handler(ctx) {
dayjs.extend(utc);
dayjs.extend(timezone);
const serie = ctx.req.param('serie');
const category = ctx.req.param('category');
const rootUrl = `https://www.lovelive-anime.jp/common/api/calendar_list.php`;
const rootUrl = 'https://www.lovelive-anime.jp/common/api/calendar_list.php';
const nowTime = dayjs();
const dataPara = {
year: nowTime.year(),
@ -49,7 +62,6 @@ async function handler(ctx) {
title,
category,
description: renderDescription({
title,
desc: item.event_dspdate,
startTime: eventStartDate,
endTime: eventEndDate,

View File

@ -1 +1 @@
{{title}}<br><img src="{{imglink}}">
<img src="{{imglink}}">

View File

@ -1,3 +1,2 @@
<h1>{{title}}</h1><br>
<b>{{startTime}}</b>&nbsp;&nbsp;&nbsp;~&nbsp;&nbsp;&nbsp;<b>{{endTime}}</b><br><br>
{{desc}}

View File

@ -27,7 +27,7 @@ export const route: Route = {
supportPodcast: false,
supportScihub: false,
},
name: 'Love Live Official Website Categories Topics',
name: 'Categories Topics',
maintainers: ['axojhf'],
handler,
description: `| Sub-project Name (not full name) | Lovelive! | Lovelive! Sunshine!! | Lovelive! Nijigasaki High School Idol Club | Lovelive! Superstar!! | 幻日のヨハネ | ラブライブ!スクールアイドルミュージカル |