mirror of
https://github.com/DIYgod/RSSHub.git
synced 2025-12-04 11:07:54 +08:00
feat: radar rules api
This commit is contained in:
7
lib/api/index.ts
Normal file
7
lib/api/index.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { Hono } from 'hono';
|
||||
import rules from '@/api/radar/rules';
|
||||
|
||||
const app = new Hono();
|
||||
app.get('/radar/rules.json', rules);
|
||||
|
||||
export default app;
|
||||
41
lib/api/radar/rules.ts
Normal file
41
lib/api/radar/rules.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import type { Handler } from 'hono';
|
||||
import { namespaces } from '@/registry';
|
||||
import { parse } from 'tldts';
|
||||
import { Radar } from '@/types';
|
||||
|
||||
const radar: Radar = {};
|
||||
|
||||
for (const namespace in namespaces) {
|
||||
for (const path in namespaces[namespace].routes) {
|
||||
const realPath = `/${namespace}${path}`;
|
||||
const data = namespaces[namespace].routes[path];
|
||||
if (data.radar && data.radar.source) {
|
||||
const parsedDomain = parse(new URL('https://' + data.radar.source[0]).hostname);
|
||||
const subdomain = parsedDomain.subdomain || '.';
|
||||
const domain = parsedDomain.domain;
|
||||
if (domain) {
|
||||
if (!radar[domain]) {
|
||||
radar[domain] = {
|
||||
_name: namespaces[namespace].name,
|
||||
};
|
||||
}
|
||||
if (!radar[domain][subdomain]) {
|
||||
radar[domain][subdomain] = [];
|
||||
}
|
||||
radar[domain][subdomain].push({
|
||||
title: data.name,
|
||||
docs: `https://docs.rsshub.app/routes/${data.categories?.[0] || 'other'}`,
|
||||
source: data.radar.source.map((source) => {
|
||||
const sourceURL = new URL('https://' + source);
|
||||
return sourceURL.pathname + sourceURL.search + sourceURL.hash;
|
||||
}),
|
||||
target: data.radar.target || realPath,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const handler: Handler = (ctx) => ctx.json(radar);
|
||||
|
||||
export default handler;
|
||||
@@ -17,6 +17,7 @@ import logger from '@/utils/logger';
|
||||
|
||||
import { notFoundHandler, errorHandler } from '@/errors';
|
||||
import registry from '@/registry';
|
||||
import api from '@/api';
|
||||
|
||||
process.on('uncaughtException', (e) => {
|
||||
logger.error('uncaughtException: ' + e);
|
||||
@@ -36,7 +37,8 @@ app.use(antiHotlink);
|
||||
app.use(parameter);
|
||||
app.use(cache);
|
||||
|
||||
registry(app);
|
||||
app.route('/', registry);
|
||||
app.route('/api', api);
|
||||
|
||||
app.notFound(notFoundHandler);
|
||||
app.onError(errorHandler);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { Namespace, Route } from '@/types';
|
||||
import { directoryImport } from 'directory-import';
|
||||
import type { Hono, Handler } from 'hono';
|
||||
import { Hono, type Handler } from 'hono';
|
||||
import * as path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { serveStatic } from '@hono/node-server/serve-static';
|
||||
@@ -91,7 +91,7 @@ if (Object.keys(modules).length) {
|
||||
|
||||
export { namespaces };
|
||||
|
||||
export default function (app: Hono) {
|
||||
const app = new Hono();
|
||||
for (const namespace in namespaces) {
|
||||
const subApp = app.basePath(`/${namespace}`);
|
||||
for (const path in namespaces[namespace].routes) {
|
||||
@@ -108,10 +108,8 @@ export default function (app: Hono) {
|
||||
}
|
||||
}
|
||||
|
||||
// routes without rss data
|
||||
app.get('/', index);
|
||||
app.get('/robots.txt', robotstxt);
|
||||
|
||||
app.use(
|
||||
'/*',
|
||||
serveStatic({
|
||||
@@ -119,4 +117,5 @@ export default function (app: Hono) {
|
||||
rewriteRequestPath: (path) => (path === '/favicon.ico' ? '/favicon.png' : path),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
export default app;
|
||||
|
||||
19
lib/types.ts
19
lib/types.ts
@@ -1,5 +1,6 @@
|
||||
import type { Context } from 'hono';
|
||||
|
||||
// rss
|
||||
export type DataItem = {
|
||||
title: string;
|
||||
description?: string;
|
||||
@@ -46,6 +47,7 @@ export type Data = {
|
||||
lastBuildDate?: string;
|
||||
};
|
||||
|
||||
// namespace
|
||||
interface NamespaceItem {
|
||||
name: string;
|
||||
url?: string;
|
||||
@@ -61,6 +63,7 @@ interface Namespace extends NamespaceItem {
|
||||
|
||||
export type { Namespace };
|
||||
|
||||
// route
|
||||
interface RouteItem {
|
||||
path: string | string[];
|
||||
name: string;
|
||||
@@ -100,3 +103,19 @@ interface Route extends RouteItem {
|
||||
}
|
||||
|
||||
export type { Route };
|
||||
|
||||
// radar
|
||||
export type Radar = {
|
||||
[domain: string]:
|
||||
| {
|
||||
[subdomain: string]: {
|
||||
title: string;
|
||||
docs: string;
|
||||
source: string[];
|
||||
target: string | ((params: any, url: string) => string);
|
||||
}[];
|
||||
}
|
||||
| {
|
||||
_name: string;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -109,6 +109,7 @@
|
||||
"telegram": "2.20.2",
|
||||
"tiny-async-pool": "2.1.0",
|
||||
"title": "3.5.3",
|
||||
"tldts": "6.1.13",
|
||||
"tough-cookie": "4.1.3",
|
||||
"tsx": "4.7.1",
|
||||
"twitter-api-v2": "1.16.1",
|
||||
@@ -172,7 +173,6 @@
|
||||
"staged-git-files": "1.3.0",
|
||||
"string-width": "7.1.0",
|
||||
"supertest": "6.3.4",
|
||||
"tldts": "6.1.13",
|
||||
"to-vfile": "8.0.0",
|
||||
"tosource": "2.0.0-alpha.3",
|
||||
"typescript": "5.4.2",
|
||||
|
||||
10
pnpm-lock.yaml
generated
10
pnpm-lock.yaml
generated
@@ -194,6 +194,9 @@ dependencies:
|
||||
title:
|
||||
specifier: 3.5.3
|
||||
version: 3.5.3
|
||||
tldts:
|
||||
specifier: 6.1.13
|
||||
version: 6.1.13
|
||||
tough-cookie:
|
||||
specifier: 4.1.3
|
||||
version: 4.1.3
|
||||
@@ -379,9 +382,6 @@ devDependencies:
|
||||
supertest:
|
||||
specifier: 6.3.4
|
||||
version: 6.3.4
|
||||
tldts:
|
||||
specifier: 6.1.13
|
||||
version: 6.1.13
|
||||
to-vfile:
|
||||
specifier: 8.0.0
|
||||
version: 8.0.0
|
||||
@@ -9442,14 +9442,14 @@ packages:
|
||||
|
||||
/tldts-core@6.1.13:
|
||||
resolution: {integrity: sha512-M1XP4D13YtXARKroULnLsKKuI1NCRAbJmUGGoXqWinajIDOhTeJf/trYUyBoLVx1/Nx1KBKxCrlW57ZW9cMHAA==}
|
||||
dev: true
|
||||
dev: false
|
||||
|
||||
/tldts@6.1.13:
|
||||
resolution: {integrity: sha512-+GxHFKVHvUTg2ieNPTx3b/NpZbgJSTZEDdI4cJzTjVYDuxijeHi1tt7CHHsMjLqyc+T50VVgWs3LIb2LrXOzxw==}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
tldts-core: 6.1.13
|
||||
dev: true
|
||||
dev: false
|
||||
|
||||
/tmp@0.0.33:
|
||||
resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==}
|
||||
|
||||
@@ -1,23 +1,12 @@
|
||||
import { namespaces } from '../../lib/registry';
|
||||
import { Radar } from '../../lib/types';
|
||||
import { parse } from 'tldts';
|
||||
import fs from 'node:fs';
|
||||
import * as path from 'node:path';
|
||||
import toSource from 'tosource';
|
||||
|
||||
const maintainers: Record<string, string[]> = {};
|
||||
const radar: {
|
||||
[domain: string]: {
|
||||
_name: string;
|
||||
[subdomain: string]:
|
||||
| {
|
||||
title: string;
|
||||
docs: string;
|
||||
source: string[];
|
||||
target: string | ((params: any, url: string) => string);
|
||||
}[]
|
||||
| string;
|
||||
};
|
||||
} = {};
|
||||
const radar: Radar = {};
|
||||
const docs = {};
|
||||
|
||||
for (const namespace in namespaces) {
|
||||
|
||||
Reference in New Issue
Block a user