mirror of
https://github.com/DIYgod/RSSHub.git
synced 2026-10-24 23:42:40 +08:00
feat(route): add Niconico Mylist (#19938)
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
import { DataItem, Route } from '@/types';
|
||||
|
||||
import { getMylist, renderVideo } from './utils';
|
||||
import { parseDate } from '@/utils/parse-date';
|
||||
|
||||
export const route: Route = {
|
||||
name: 'Mylist',
|
||||
path: '/mylist/:id',
|
||||
parameters: { id: 'Mylist ID' },
|
||||
example: '/nicovideo/mylist/2973737',
|
||||
maintainers: ['esperecyan'],
|
||||
radar: [
|
||||
{
|
||||
source: ['www.nicovideo.jp/user/:user/mylist/:id'],
|
||||
target: '/mylist/:id',
|
||||
},
|
||||
],
|
||||
handler: async (ctx) => {
|
||||
const { id } = ctx.req.param();
|
||||
|
||||
const mylist = await getMylist(id);
|
||||
|
||||
return {
|
||||
title: `マイリスト ${mylist.name}‐ニコニコ動画`,
|
||||
link: `https://www.nicovideo.jp/user/${mylist.owner.id}/mylist/${mylist.id}`,
|
||||
language: 'ja',
|
||||
item: mylist.items.map(
|
||||
(item): DataItem => ({
|
||||
title: item.video.title,
|
||||
link: `https://www.nicovideo.jp/watch/${item.video.id}`,
|
||||
pubDate: parseDate(item.addedAt),
|
||||
author: [{ name: item.video.owner.name, avatar: item.video.owner.iconUrl, url: `https://www.nicovideo.jp/user/${item.video.owner.id}` }],
|
||||
description: renderVideo(item.video, false),
|
||||
image: item.video.thumbnail.nHdUrl ?? item.video.thumbnail.largeUrl ?? item.video.thumbnail.middleUrl ?? undefined,
|
||||
})
|
||||
),
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -52,3 +52,30 @@ export interface VideoItem {
|
||||
series: null;
|
||||
essential: Essential;
|
||||
}
|
||||
|
||||
export type Mylist = {
|
||||
id: number;
|
||||
name: string;
|
||||
description: string;
|
||||
decoratedDescriptionHtml: string;
|
||||
defaultSortKey: string;
|
||||
defaultSortOrder: string;
|
||||
items: MylistItem[];
|
||||
totalItemCount: number;
|
||||
hasNext: boolean;
|
||||
isPublic: boolean;
|
||||
owner: Owner;
|
||||
hasInvisibleItems: boolean;
|
||||
followerCount: number;
|
||||
isFollowing: boolean;
|
||||
};
|
||||
|
||||
type MylistItem = {
|
||||
itemId: number;
|
||||
watchId: string;
|
||||
description: string;
|
||||
decoratedDescriptionHtml: string;
|
||||
addedAt: string;
|
||||
status: string;
|
||||
video: Essential;
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Essential, UserInfo, VideoItem } from './types';
|
||||
import { Essential, Mylist, UserInfo, VideoItem } from './types';
|
||||
|
||||
import ofetch from '@/utils/ofetch';
|
||||
import cache from '@/utils/cache';
|
||||
@@ -31,4 +31,30 @@ export const getUserVideosById = (id: string) =>
|
||||
false
|
||||
) as Promise<VideoItem[]>;
|
||||
|
||||
export const getMylist = (id: string): Promise<Mylist> =>
|
||||
cache.tryGet<Mylist>(
|
||||
`nicovideo:mylist:${id}`,
|
||||
async () => {
|
||||
const { data } = await ofetch(`https://nvapi.nicovideo.jp/v2/mylists/${id}`, {
|
||||
headers: {
|
||||
'X-Frontend-Id': '6',
|
||||
},
|
||||
query: {
|
||||
sortKey: 'addedAt',
|
||||
sortOrder: 'desc',
|
||||
/**
|
||||
* @remarks
|
||||
* Up to 500 items can be registered in a single mylist.
|
||||
* @see https://qa.nicovideo.jp/faq/show/648?site_domain=default
|
||||
*/
|
||||
pageSize: 500,
|
||||
page: 1,
|
||||
},
|
||||
});
|
||||
return data.mylist;
|
||||
},
|
||||
config.cache.routeExpire,
|
||||
false
|
||||
);
|
||||
|
||||
export const renderVideo = (video: Essential, embed: boolean) => art(path.join(__dirname, 'templates/video.art'), { video, embed });
|
||||
|
||||
Reference in New Issue
Block a user