feat: next generation routing registration method

This commit is contained in:
DIYgod
2024-03-08 16:45:05 +08:00
parent 2c8711bf52
commit d4771fcbc4
5 changed files with 174 additions and 2 deletions
+4 -2
View File
@@ -15,8 +15,9 @@ import parameter from '@/middleware/parameter';
import logger from '@/utils/logger';
import initRoutes from '@/init-routes';
// import initRoutes from '@/init-routes';
import { notFoundHandler, errorHandler } from '@/errors';
import registry from '@/registry';
process.on('uncaughtException', (e) => {
logger.error('uncaughtException: ' + e);
@@ -36,7 +37,8 @@ app.use(antiHotlink);
app.use(parameter);
app.use(cache);
initRoutes(app);
// initRoutes(app);
registry(app);
app.notFound(notFoundHandler);
app.onError(errorHandler);
+57
View File
@@ -0,0 +1,57 @@
import type { Namespace, Route } from '@/types';
import { directoryImport } from 'directory-import';
import type { Hono, Handler } from 'hono';
import * as path from 'node:path';
const modules = directoryImport({
targetDirectoryPath: path.join(__dirname, './routes-new'),
importPattern: /\.ts$/,
});
const namespaces: Record<
string,
Namespace & {
routes: Record<string, Route>;
}
> = {};
for (const module in modules) {
const content = modules[module] as
| {
route: Route;
}
| {
namespace: Namespace;
};
const namespace = module.split('/')[1];
if ('namespace' in content) {
namespaces[namespace] = Object.assign(
{
routes: {},
},
namespaces[namespace],
content.namespace
);
} else if ('route' in content) {
if (!namespaces[namespace]) {
namespaces[namespace] = {
name: namespace,
routes: {},
};
}
namespaces[namespace].routes[content.route.path] = content.route;
}
}
export default function (app: Hono) {
for (const namespace in namespaces) {
const subApp = app.basePath(`/${namespace}`);
for (const path in namespaces[namespace].routes) {
const wrapedHandler: Handler = async (ctx) => {
if (!ctx.get('data')) {
ctx.set('data', await namespaces[namespace].routes[path].handler(ctx));
}
};
subApp.get(path, wrapedHandler);
}
}
}
+72
View File
@@ -0,0 +1,72 @@
import got from '@/utils/got';
import type { Route } from '@/types';
export const route: Route = {
path: '/bangumi/media/:mediaid',
categories: ['new-media'],
example: '/bilibili/bangumi/media/9192',
parameters: {
mediaid: '番剧媒体 id, 番剧主页 URL 中获取',
},
features: {
requireConfig: false,
requirePuppeteer: false,
antiCrawler: false,
supportRadar: false,
supportBT: false,
supportPodcast: false,
supportScihub: false,
},
name: '番剧',
maintainers: ['DIYgod'],
handler: async (ctx) => {
let seasonid = ctx.req.param('seasonid');
const mediaid = ctx.req.param('mediaid');
let mediaData;
if (mediaid) {
const response = await got({
method: 'get',
url: `https://www.bilibili.com/bangumi/media/md${mediaid}`,
});
mediaData = JSON.parse(response.data.match(/window\.__INITIAL_STATE__=([\S\s]+);\(function\(\)/)[1]) || {};
seasonid = mediaData.mediaInfo.season_id;
}
const { data } = await got.get(`https://api.bilibili.com/pgc/web/season/section?season_id=${seasonid}`);
let episodes = [];
if (data.result.main_section && data.result.main_section.episodes) {
episodes = [
...episodes,
...data.result.main_section.episodes.map((item) => ({
title: `第${item.title}话 ${item.long_title}`,
description: `<img src="${item.cover}">`,
link: `https://www.bilibili.com/bangumi/play/ep${item.id}`,
})),
];
}
if (data.result.section) {
for (const section of data.result.section) {
if (section.episodes) {
episodes = [
...episodes,
...section.episodes.map((item) => ({
title: `${item.title} ${item.long_title}`,
description: `<img src="${item.cover}">`,
link: `https://www.bilibili.com/bangumi/play/ep${item.id}`,
})),
];
}
}
}
return {
title: mediaData?.mediaInfo.title,
link: `https://www.bilibili.com/bangumi/media/md${mediaData?.mediaInfo.media_id}/`,
image: mediaData?.mediaInfo.cover,
description: mediaData?.mediaInfo.evaluate,
item: episodes,
};
},
};
+6
View File
@@ -0,0 +1,6 @@
import type { Namespace } from '@/types';
export const namespace: Namespace = {
name: 'Bilibili',
url: 'www.bilibili.com',
};
+35
View File
@@ -1,3 +1,5 @@
import type { Context } from 'hono';
export type DataItem = {
title: string;
description?: string;
@@ -43,3 +45,36 @@ export type Data = {
feedLink?: string;
lastBuildDate?: string;
};
export type Namespace = {
name: string;
url?: string;
categories?: string[];
description?: string;
};
export type Route = {
path: string;
name: string;
url?: string;
maintainers: string[];
handler: (ctx: Context) => Promise<Data> | Data;
example: string;
parameters?: Record<string, string>;
description?: string;
categories?: string[];
features: {
requireConfig?: string[] | false;
requirePuppeteer?: boolean;
antiCrawler?: boolean;
supportRadar?: boolean;
supportBT?: boolean;
supportPodcast?: boolean;
supportScihub?: boolean;
};
radar?: {
source: string[];
target?: string;
};
};