feat: add ConfigNotFoundError and InvalidParameterError
This commit is contained in:
parent
cef1ed1eb6
commit
79fcce2729
|
|
@ -0,0 +1,5 @@
|
|||
class ConfigNotFoundError extends Error {
|
||||
name = 'ConfigNotFoundError';
|
||||
}
|
||||
|
||||
export default ConfigNotFoundError;
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
class InvalidParameterError extends Error {
|
||||
name = 'InvalidParameterError';
|
||||
}
|
||||
|
||||
export default InvalidParameterError;
|
||||
|
|
@ -7,6 +7,7 @@ import got from '@/utils/got';
|
|||
import { art } from '@/utils/render';
|
||||
import path from 'node:path';
|
||||
import { config } from '@/config';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
const rootUrl = 'https://kyfw.12306.cn';
|
||||
|
||||
|
|
@ -85,7 +86,7 @@ async function handler(ctx) {
|
|||
},
|
||||
});
|
||||
if (response.data.data === undefined || response.data.data.length === 0) {
|
||||
throw new Error('没有找到相关车次,请检查参数是否正确');
|
||||
throw new InvalidParameterError('没有找到相关车次,请检查参数是否正确');
|
||||
}
|
||||
const data = response.data.data.result;
|
||||
const map = response.data.data.map;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import got from '@/utils/got';
|
|||
import { load } from 'cheerio';
|
||||
import iconv from 'iconv-lite';
|
||||
import { parseDate } from '@/utils/parse-date';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
const rootUrl = 'https://news.163.com';
|
||||
|
||||
|
|
@ -119,9 +120,9 @@ async function handler(ctx) {
|
|||
|
||||
const cfg = config[category];
|
||||
if (!cfg) {
|
||||
throw new Error('Bad category. See <a href="https://docs.rsshub.app/routes/new-media#wang-yi-xin-wen-pai-hang-bang">docs</a>');
|
||||
throw new InvalidParameterError('Bad category. See <a href="https://docs.rsshub.app/routes/new-media#wang-yi-xin-wen-pai-hang-bang">docs</a>');
|
||||
} else if ((category !== 'whole' && type === 'click' && time === 'month') || (category === 'whole' && type === 'click' && time === 'hour') || (type === 'follow' && time === 'hour')) {
|
||||
throw new Error('Bad timeRange range. See <a href="https://docs.rsshub.app/routes/new-media#wang-yi-xin-wen-pai-hang-bang">docs</a>');
|
||||
throw new InvalidParameterError('Bad timeRange range. See <a href="https://docs.rsshub.app/routes/new-media#wang-yi-xin-wen-pai-hang-bang">docs</a>');
|
||||
}
|
||||
|
||||
const currentUrl = category === 'money' ? cfg.link : `${rootUrl}${cfg.link}`;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
import { Route } from '@/types';
|
||||
import cache from '@/utils/cache';
|
||||
import got from '@/utils/got';
|
||||
|
|
@ -43,7 +44,7 @@ export const route: Route = {
|
|||
|
||||
async function handler(ctx) {
|
||||
if (!ctx.req.param('type')) {
|
||||
throw new Error('Bad parameter. See <a href="https://docs.rsshub.app/routes/game#wang-yi-da-shen">https://docs.rsshub.app/routes/game#wang-yi-da-shen</a>');
|
||||
throw new InvalidParameterError('Bad parameter. See <a href="https://docs.rsshub.app/routes/game#wang-yi-da-shen">https://docs.rsshub.app/routes/game#wang-yi-da-shen</a>');
|
||||
}
|
||||
const selectedType = Number.parseInt(ctx.req.param('type'));
|
||||
let type;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { parseDate } from '@/utils/parse-date';
|
|||
import { art } from '@/utils/render';
|
||||
import path from 'node:path';
|
||||
import { config } from '@/config';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
|
||||
const defaultDomain = 'jmcomic1.me';
|
||||
// list of address: https://jmcomic2.bet
|
||||
|
|
@ -15,7 +16,7 @@ const allowDomain = new Set(['18comic.vip', '18comic.org', 'jmcomic.me', 'jmcomi
|
|||
|
||||
const getRootUrl = (domain) => {
|
||||
if (!config.feature.allow_user_supply_unsafe_domain && !allowDomain.has(domain)) {
|
||||
throw new Error(`This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.`);
|
||||
throw new ConfigNotFoundError(`This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.`);
|
||||
}
|
||||
|
||||
return `https://${domain}`;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import timezone from '@/utils/timezone';
|
|||
import { parseDate } from '@/utils/parse-date';
|
||||
import iconv from 'iconv-lite';
|
||||
import { isValidHost } from '@/utils/valid-host';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
const setCookie = function (cookieName, cookieValue, seconds, path, domain, secure) {
|
||||
let expires = null;
|
||||
|
|
@ -52,7 +53,7 @@ export const route: Route = {
|
|||
async function handler(ctx) {
|
||||
const city = ctx.req.param('city') ?? 'www';
|
||||
if (!isValidHost(city)) {
|
||||
throw new Error('Invalid city');
|
||||
throw new InvalidParameterError('Invalid city');
|
||||
}
|
||||
|
||||
const rootUrl = `https://${city}.19lou.com`;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import got from '@/utils/got';
|
|||
import path from 'node:path';
|
||||
import { art } from '@/utils/render';
|
||||
import { parseDate } from '@/utils/parse-date';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
const getCategories = (tryGet) =>
|
||||
tryGet('4gamers:categories', async () => {
|
||||
|
|
@ -48,7 +49,7 @@ const parseItem = async (item) => {
|
|||
case 'ImageGroupSection':
|
||||
return renderImages(section.items);
|
||||
default:
|
||||
throw new Error(`Unhandled section type: ${section['@type']} on ${item.link}`);
|
||||
throw new InvalidParameterError(`Unhandled section type: ${section['@type']} on ${item.link}`);
|
||||
}
|
||||
})
|
||||
.join('')
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { load } from 'cheerio';
|
|||
import got from '@/utils/got';
|
||||
import { art } from '@/utils/render';
|
||||
import { isValidHost } from '@/utils/valid-host';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
const cookieJar = new CookieJar();
|
||||
|
||||
|
|
@ -133,7 +134,7 @@ async function handler(ctx) {
|
|||
const country = ctx.req.param('country') ?? 'tw';
|
||||
|
||||
if (!isValidHost(country) && country !== 'tw') {
|
||||
throw new Error('Invalid country codes. Only "tw" is supported now.');
|
||||
throw new InvalidParameterError('Invalid country codes. Only "tw" is supported now.');
|
||||
}
|
||||
|
||||
/** @type {House[]} */
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
import { config } from '@/config';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
const allowDomain = new Set(['91porn.com', 'www.91porn.com', '0122.91p30.com', 'www.91zuixindizhi.com', 'w1218.91p46.com']);
|
||||
|
||||
const domainValidation = (domain) => {
|
||||
if (!config.feature.allow_user_supply_unsafe_domain && !allowDomain.has(domain)) {
|
||||
throw new Error(`This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.`);
|
||||
throw new ConfigNotFoundError(`This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.`);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import cache from '@/utils/cache';
|
|||
import got from '@/utils/got';
|
||||
import { load } from 'cheerio';
|
||||
import { parseDate } from '@/utils/parse-date';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
const baseUrl = 'https://www.acfun.cn';
|
||||
const categoryMap = {
|
||||
|
|
@ -66,13 +67,13 @@ export const route: Route = {
|
|||
async function handler(ctx) {
|
||||
const { categoryId, sortType = 'createTime', timeRange = 'all' } = ctx.req.param();
|
||||
if (!categoryMap[categoryId]) {
|
||||
throw new Error(`Invalid category Id: ${categoryId}`);
|
||||
throw new InvalidParameterError(`Invalid category Id: ${categoryId}`);
|
||||
}
|
||||
if (!sortTypeEnum.has(sortType)) {
|
||||
throw new Error(`Invalid sort type: ${sortType}`);
|
||||
throw new InvalidParameterError(`Invalid sort type: ${sortType}`);
|
||||
}
|
||||
if (!timeRangeEnum.has(timeRange)) {
|
||||
throw new Error(`Invalid time range: ${timeRange}`);
|
||||
throw new InvalidParameterError(`Invalid time range: ${timeRange}`);
|
||||
}
|
||||
|
||||
const url = `${baseUrl}/v/list${categoryId}/index.htm`;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { puppeteerGet, renderDesc } from './utils';
|
|||
import { config } from '@/config';
|
||||
import { isValidHost } from '@/utils/valid-host';
|
||||
import puppeteer from '@/utils/puppeteer';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
const handler = async (ctx) => {
|
||||
const pub = ctx.req.param('pub');
|
||||
|
|
@ -11,7 +12,7 @@ const handler = async (ctx) => {
|
|||
const host = `https://pubs.aip.org`;
|
||||
const jrnlUrl = `${host}/${pub}/${jrn}/issue`;
|
||||
if (!isValidHost(pub)) {
|
||||
throw new Error('Invalid pub');
|
||||
throw new InvalidParameterError('Invalid pub');
|
||||
}
|
||||
|
||||
// use Puppeteer due to the obstacle by cloudflare challenge
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import got from '@/utils/got';
|
|||
import { load } from 'cheerio';
|
||||
|
||||
import { rootUrl, ossUrl, ProcessFeed } from './utils';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/thinktank/:id/:type?',
|
||||
|
|
@ -43,7 +44,7 @@ async function handler(ctx) {
|
|||
.toArray()
|
||||
.filter((h) => (type ? $(h).text() === type : true));
|
||||
if (!targetList) {
|
||||
throw new Error(`Not found ${type} in ${id}: ${currentUrl}`);
|
||||
throw new InvalidParameterError(`Not found ${type} in ${id}: ${currentUrl}`);
|
||||
}
|
||||
|
||||
for (const l of targetList) {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import getComments from './comments';
|
|||
import getFromAPI from './offcial-subject-api';
|
||||
import getEps from './ep';
|
||||
import { queryToBoolean } from '@/utils/readable-social';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/tv/subject/:id/:type?/:showOriginalName?',
|
||||
|
|
@ -50,7 +51,7 @@ async function handler(ctx) {
|
|||
response = await getFromAPI('topic')(id, showOriginalName);
|
||||
break;
|
||||
default:
|
||||
throw new Error(`暂不支持对${type}的订阅`);
|
||||
throw new InvalidParameterError(`暂不支持对${type}的订阅`);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import { art } from '@/utils/render';
|
|||
import path from 'node:path';
|
||||
import asyncPool from 'tiny-async-pool';
|
||||
import { config } from '@/config';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
|
||||
// Visit https://www.bdys.me for the list of domains
|
||||
const allowDomains = new Set(['52bdys.com', 'bde4.icu', 'bdys01.com']);
|
||||
|
|
@ -107,7 +108,7 @@ async function handler(ctx) {
|
|||
|
||||
const site = ctx.req.query('domain') || 'bdys01.com';
|
||||
if (!config.feature.allow_user_supply_unsafe_domain && !allowDomains.has(new URL(`https://${site}`).hostname)) {
|
||||
throw new Error(`This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.`);
|
||||
throw new ConfigNotFoundError(`This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.`);
|
||||
}
|
||||
|
||||
const rootUrl = `https://www.${site}`;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { load } from 'cheerio';
|
|||
import timezone from '@/utils/timezone';
|
||||
import { parseDate } from '@/utils/parse-date';
|
||||
import { isValidHost } from '@/utils/valid-host';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/news/:city',
|
||||
|
|
@ -43,7 +44,7 @@ export const route: Route = {
|
|||
async function handler(ctx) {
|
||||
const city = ctx.req.param('city');
|
||||
if (!isValidHost(city)) {
|
||||
throw new Error('Invalid city');
|
||||
throw new InvalidParameterError('Invalid city');
|
||||
}
|
||||
|
||||
const rootUrl = `http://${city}.bendibao.com`;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { Route } from '@/types';
|
|||
import got from '@/utils/got';
|
||||
import cache from './cache';
|
||||
import { config } from '@/config';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/user/followers/:uid/:loginUid',
|
||||
|
|
@ -45,7 +46,7 @@ async function handler(ctx) {
|
|||
|
||||
const cookie = config.bilibili.cookies[loginUid];
|
||||
if (cookie === undefined) {
|
||||
throw new Error('缺少对应 loginUid 的 Bilibili 用户登录后的 Cookie 值 <a href="https://docs.rsshub.app/zh/deploy/config#route-specific-configurations">bilibili 用户关注动态系列路由</a>');
|
||||
throw new ConfigNotFoundError('缺少对应 loginUid 的 Bilibili 用户登录后的 Cookie 值 <a href="https://docs.rsshub.app/zh/deploy/config#route-specific-configurations">bilibili 用户关注动态系列路由</a>');
|
||||
}
|
||||
|
||||
const name = await cache.getUsernameFromUID(uid);
|
||||
|
|
@ -68,7 +69,7 @@ async function handler(ctx) {
|
|||
},
|
||||
});
|
||||
if (response.data.code === -6 || response.data.code === -101) {
|
||||
throw new Error('对应 loginUid 的 Bilibili 用户的 Cookie 已过期');
|
||||
throw new ConfigNotFoundError('对应 loginUid 的 Bilibili 用户的 Cookie 已过期');
|
||||
}
|
||||
const data = response.data.data.list;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { Route } from '@/types';
|
|||
import got from '@/utils/got';
|
||||
import cache from './cache';
|
||||
import { config } from '@/config';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/followings/article/:uid',
|
||||
|
|
@ -39,7 +40,7 @@ async function handler(ctx) {
|
|||
|
||||
const cookie = config.bilibili.cookies[uid];
|
||||
if (cookie === undefined) {
|
||||
throw new Error('缺少对应 uid 的 Bilibili 用户登录后的 Cookie 值');
|
||||
throw new ConfigNotFoundError('缺少对应 uid 的 Bilibili 用户登录后的 Cookie 值');
|
||||
}
|
||||
|
||||
const response = await got({
|
||||
|
|
@ -51,7 +52,7 @@ async function handler(ctx) {
|
|||
},
|
||||
});
|
||||
if (response.data.code === -6) {
|
||||
throw new Error('对应 uid 的 Bilibili 用户的 Cookie 已过期');
|
||||
throw new ConfigNotFoundError('对应 uid 的 Bilibili 用户的 Cookie 已过期');
|
||||
}
|
||||
const cards = response.data.data.cards;
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import utils from './utils';
|
|||
import JSONbig from 'json-bigint';
|
||||
import { fallback, queryToBoolean } from '@/utils/readable-social';
|
||||
import querystring from 'querystring';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/followings/dynamic/:uid/:routeParams?',
|
||||
|
|
@ -49,7 +50,7 @@ async function handler(ctx) {
|
|||
|
||||
const cookie = config.bilibili.cookies[uid];
|
||||
if (cookie === undefined) {
|
||||
throw new Error('缺少对应 uid 的 Bilibili 用户登录后的 Cookie 值');
|
||||
throw new ConfigNotFoundError('缺少对应 uid 的 Bilibili 用户登录后的 Cookie 值');
|
||||
}
|
||||
|
||||
const response = await got({
|
||||
|
|
@ -61,7 +62,7 @@ async function handler(ctx) {
|
|||
},
|
||||
});
|
||||
if (response.data.code === -6) {
|
||||
throw new Error('对应 uid 的 Bilibili 用户的 Cookie 已过期');
|
||||
throw new ConfigNotFoundError('对应 uid 的 Bilibili 用户的 Cookie 已过期');
|
||||
}
|
||||
const data = JSONbig.parse(response.body).data.cards;
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import got from '@/utils/got';
|
|||
import cache from './cache';
|
||||
import { config } from '@/config';
|
||||
import utils from './utils';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/followings/video/:uid/:disableEmbed?',
|
||||
|
|
@ -41,7 +42,7 @@ async function handler(ctx) {
|
|||
|
||||
const cookie = config.bilibili.cookies[uid];
|
||||
if (cookie === undefined) {
|
||||
throw new Error('缺少对应 uid 的 Bilibili 用户登录后的 Cookie 值');
|
||||
throw new ConfigNotFoundError('缺少对应 uid 的 Bilibili 用户登录后的 Cookie 值');
|
||||
}
|
||||
|
||||
const response = await got({
|
||||
|
|
@ -53,7 +54,7 @@ async function handler(ctx) {
|
|||
},
|
||||
});
|
||||
if (response.data.code === -6) {
|
||||
throw new Error('对应 uid 的 Bilibili 用户的 Cookie 已过期');
|
||||
throw new ConfigNotFoundError('对应 uid 的 Bilibili 用户的 Cookie 已过期');
|
||||
}
|
||||
const cards = response.data.data.cards;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ import { Route } from '@/types';
|
|||
import got from '@/utils/got';
|
||||
import cache from './cache';
|
||||
import { config } from '@/config';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/user/followings/:uid/:loginUid',
|
||||
|
|
@ -43,7 +45,7 @@ async function handler(ctx) {
|
|||
const loginUid = ctx.req.param('loginUid');
|
||||
const cookie = config.bilibili.cookies[loginUid];
|
||||
if (cookie === undefined) {
|
||||
throw new Error('缺少对应 loginUid 的 Bilibili 用户登录后的 Cookie 值 <a href="https://docs.rsshub.app/zh/deploy/config#route-specific-configurations">bilibili 用户关注动态系列路由</a>');
|
||||
throw new ConfigNotFoundError('缺少对应 loginUid 的 Bilibili 用户登录后的 Cookie 值 <a href="https://docs.rsshub.app/zh/deploy/config#route-specific-configurations">bilibili 用户关注动态系列路由</a>');
|
||||
}
|
||||
|
||||
const uid = ctx.req.param('uid');
|
||||
|
|
@ -67,11 +69,11 @@ async function handler(ctx) {
|
|||
},
|
||||
});
|
||||
if (response.data.code === -6) {
|
||||
throw new Error('对应 loginUid 的 Bilibili 用户的 Cookie 已过期');
|
||||
throw new ConfigNotFoundError('对应 loginUid 的 Bilibili 用户的 Cookie 已过期');
|
||||
}
|
||||
// 22115 : 用户已设置隐私,无法查看
|
||||
if (response.data.code === 22115) {
|
||||
throw new Error(response.data.message);
|
||||
throw new InvalidParameterError(response.data.message);
|
||||
}
|
||||
const data = response.data.data.list;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { Route } from '@/types';
|
|||
import got from '@/utils/got';
|
||||
import cache from './cache';
|
||||
import { config } from '@/config';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/manga/followings/:uid/:limits?',
|
||||
|
|
@ -39,7 +40,7 @@ async function handler(ctx) {
|
|||
|
||||
const cookie = config.bilibili.cookies[uid];
|
||||
if (cookie === undefined) {
|
||||
throw new Error('缺少对应 uid 的 Bilibili 用户登录后的 Cookie 值');
|
||||
throw new ConfigNotFoundError('缺少对应 uid 的 Bilibili 用户登录后的 Cookie 值');
|
||||
}
|
||||
const page_size = ctx.req.param('limits') || 10;
|
||||
const link = 'https://manga.bilibili.com/account-center';
|
||||
|
|
@ -53,7 +54,7 @@ async function handler(ctx) {
|
|||
},
|
||||
});
|
||||
if (response.data.code === -6) {
|
||||
throw new Error('对应 uid 的 Bilibili 用户的 Cookie 已过期');
|
||||
throw new ConfigNotFoundError('对应 uid 的 Bilibili 用户的 Cookie 已过期');
|
||||
}
|
||||
const comics = response.data.data;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import cache from './cache';
|
|||
import { config } from '@/config';
|
||||
import utils from './utils';
|
||||
import { parseDate } from '@/utils/parse-date';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/watchlater/:uid/:disableEmbed?',
|
||||
|
|
@ -42,7 +43,7 @@ async function handler(ctx) {
|
|||
|
||||
const cookie = config.bilibili.cookies[uid];
|
||||
if (cookie === undefined) {
|
||||
throw new Error('缺少对应 uid 的 Bilibili 用户登录后的 Cookie 值');
|
||||
throw new ConfigNotFoundError('缺少对应 uid 的 Bilibili 用户登录后的 Cookie 值');
|
||||
}
|
||||
|
||||
const response = await got({
|
||||
|
|
@ -55,7 +56,7 @@ async function handler(ctx) {
|
|||
});
|
||||
if (response.data.code) {
|
||||
const message = response.data.code === -6 ? '对应 uid 的 Bilibili 用户的 Cookie 已过期' : response.data.message;
|
||||
throw new Error(`Error code ${response.data.code}: ${message}`);
|
||||
throw new ConfigNotFoundError(`Error code ${response.data.code}: ${message}`);
|
||||
}
|
||||
const list = response.data.data.list || [];
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import iconv from 'iconv-lite';
|
|||
import timezone from '@/utils/timezone';
|
||||
import { parseDate } from '@/utils/parse-date';
|
||||
import { config } from '@/config';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
const allowHost = new Set([
|
||||
'www.xbiquwx.la',
|
||||
'www.biqu5200.net',
|
||||
|
|
@ -36,7 +37,7 @@ async function handler(ctx) {
|
|||
const rootUrl = getSubPath(ctx).split('/').slice(1, 4).join('/');
|
||||
const currentUrl = getSubPath(ctx).slice(1);
|
||||
if (!config.feature.allow_user_supply_unsafe_domain && !allowHost.has(new URL(rootUrl).hostname)) {
|
||||
throw new Error(`This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.`);
|
||||
throw new ConfigNotFoundError(`This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.`);
|
||||
}
|
||||
|
||||
const response = await got({
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { parseDate } from '@/utils/parse-date';
|
|||
import { art } from '@/utils/render';
|
||||
import path from 'node:path';
|
||||
import { config } from '@/config';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
const allowDomain = new Set(['2btjia.com', '88btbtt.com', 'btbtt15.com', 'btbtt20.com']);
|
||||
|
||||
export const route: Route = {
|
||||
|
|
@ -71,7 +72,7 @@ async function handler(ctx) {
|
|||
let category = ctx.req.param('category') ?? '';
|
||||
let domain = ctx.req.query('domain') ?? 'btbtt15.com';
|
||||
if (!config.feature.allow_user_supply_unsafe_domain && !allowDomain.has(new URL(`http://${domain}/`).hostname)) {
|
||||
throw new Error(`This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.`);
|
||||
throw new ConfigNotFoundError(`This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.`);
|
||||
}
|
||||
|
||||
if (category === 'base') {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { load } from 'cheerio';
|
|||
import { isValidHost } from '@/utils/valid-host';
|
||||
import { parseDate } from '@/utils/parse-date';
|
||||
import { parseBlogArticle } from './utils';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/blog/:column?',
|
||||
|
|
@ -30,7 +31,7 @@ async function handler(ctx) {
|
|||
const { limit = 20 } = ctx.req.query();
|
||||
if (column) {
|
||||
if (!isValidHost(column)) {
|
||||
throw new Error('Invalid column');
|
||||
throw new InvalidParameterError('Invalid column');
|
||||
}
|
||||
const link = `https://${column}.blog.caixin.com`;
|
||||
const { data: response } = await got(link);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { isValidHost } from '@/utils/valid-host';
|
|||
import { parseDate } from '@/utils/parse-date';
|
||||
import timezone from '@/utils/timezone';
|
||||
import { parseArticle } from './utils';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/:column/:category',
|
||||
|
|
@ -47,7 +48,7 @@ async function handler(ctx) {
|
|||
const column = ctx.req.param('column');
|
||||
const url = `https://${column}.caixin.com/${category}`;
|
||||
if (!isValidHost(column)) {
|
||||
throw new Error('Invalid column');
|
||||
throw new InvalidParameterError('Invalid column');
|
||||
}
|
||||
|
||||
const response = await got(url);
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { art } from '@/utils/render';
|
|||
import path from 'node:path';
|
||||
|
||||
import { rootUrl, getSearchParams } from './utils';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
const categories = {
|
||||
1000: '头条',
|
||||
|
|
@ -57,7 +58,7 @@ async function handler(ctx) {
|
|||
const title = categories[category];
|
||||
|
||||
if (!title) {
|
||||
throw new Error('Bad category. See <a href="https://docs.rsshub.app/routes/finance#cai-lian-she-shen-du">docs</a>');
|
||||
throw new InvalidParameterError('Bad category. See <a href="https://docs.rsshub.app/routes/finance#cai-lian-she-shen-du">docs</a>');
|
||||
}
|
||||
|
||||
const apiUrl = `${rootUrl}/v3/depth/home/assembled/${category}`;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { load } from 'cheerio';
|
|||
import { parseDate } from '@/utils/parse-date';
|
||||
import { art } from '@/utils/render';
|
||||
import path from 'node:path';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
const categories = {
|
||||
jxrb: '嘉兴日报',
|
||||
|
|
@ -25,7 +26,7 @@ async function handler(ctx) {
|
|||
const category = ctx.req.param('category') ?? 'jxrb';
|
||||
const id = ctx.req.param('id');
|
||||
if (!Object.keys(categories).includes(category)) {
|
||||
throw new Error('Invalid category');
|
||||
throw new InvalidParameterError('Invalid category');
|
||||
}
|
||||
|
||||
const rootUrl = `https://${category}.cnjxol.com`;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { load } from 'cheerio';
|
|||
import { parseDate } from '@/utils/parse-date';
|
||||
import { art } from '@/utils/render';
|
||||
import path from 'node:path';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/:name',
|
||||
|
|
@ -50,7 +51,7 @@ async function handler(ctx) {
|
|||
.map((el) => $(el).find('a').first().attr('href'));
|
||||
|
||||
if (links.length === 0) {
|
||||
throw new Error(`Comic Not Found - ${name}`);
|
||||
throw new InvalidParameterError(`Comic Not Found - ${name}`);
|
||||
}
|
||||
const items = await Promise.all(
|
||||
links.map((link) =>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { Route } from '@/types';
|
||||
import got from '@/utils/got';
|
||||
import utils from './utils';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/dyh/:dyhId',
|
||||
|
|
@ -48,7 +49,7 @@ async function handler(ctx) {
|
|||
|
||||
out = out.filter(Boolean); // 去除空值
|
||||
if (out.length === 0) {
|
||||
throw new Error('仅限于采集站内订阅的看看号的图文及动态内容。这个ID可能是站外订阅。');
|
||||
throw new InvalidParameterError('仅限于采集站内订阅的看看号的图文及动态内容。这个ID可能是站外订阅。');
|
||||
}
|
||||
return {
|
||||
title: `酷安看看号-${targetTitle}`,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { Route } from '@/types';
|
||||
import got from '@/utils/got';
|
||||
import utils from './utils';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/huati/:tag',
|
||||
|
|
@ -32,7 +33,7 @@ async function handler(ctx) {
|
|||
|
||||
out = out.filter(Boolean); // 去除空值
|
||||
if (out.length === 0) {
|
||||
throw new Error('这个话题还没有被创建或现在没有图文及动态内容。');
|
||||
throw new InvalidParameterError('这个话题还没有被创建或现在没有图文及动态内容。');
|
||||
}
|
||||
return {
|
||||
title: `酷安话题-${tag}`,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { Route } from '@/types';
|
||||
import got from '@/utils/got';
|
||||
import utils from './utils';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/user/:uid/dynamic',
|
||||
|
|
@ -29,7 +30,7 @@ async function handler(ctx) {
|
|||
});
|
||||
const data = response.data.data;
|
||||
if (!data) {
|
||||
throw new Error('这个人没有任何动态。');
|
||||
throw new InvalidParameterError('这个人没有任何动态。');
|
||||
}
|
||||
let out = await Promise.all(
|
||||
data.map((item) => {
|
||||
|
|
@ -43,7 +44,7 @@ async function handler(ctx) {
|
|||
|
||||
out = out.filter(Boolean); // 去除空值
|
||||
if (out.length === 0) {
|
||||
throw new Error('这个人还没有图文或动态。');
|
||||
throw new InvalidParameterError('这个人还没有图文或动态。');
|
||||
}
|
||||
return {
|
||||
title: `酷安个人动态-${username}`,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { parseDate } from '@/utils/parse-date';
|
|||
import { art } from '@/utils/render';
|
||||
import path from 'node:path';
|
||||
import { baseUrl, getChannel, getChannelMessages, getGuild } from './discord-api';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/channel/:channelId',
|
||||
|
|
@ -39,7 +40,7 @@ export const route: Route = {
|
|||
|
||||
async function handler(ctx) {
|
||||
if (!config.discord || !config.discord.authorization) {
|
||||
throw new Error('Discord RSS is disabled due to the lack of <a href="https://docs.rsshub.app/deploy/config#route-specific-configurations">relevant config</a>');
|
||||
throw new ConfigNotFoundError('Discord RSS is disabled due to the lack of <a href="https://docs.rsshub.app/deploy/config#route-specific-configurations">relevant config</a>');
|
||||
}
|
||||
const { authorization } = config.discord;
|
||||
const channelId = ctx.req.param('channelId');
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import { config } from '@/config';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
|
||||
function getConfig(ctx) {
|
||||
if (!config.discourse.config[ctx.req.param('configId')]) {
|
||||
throw new Error('Discourse RSS is disabled due to the lack of <a href="https://docs.rsshub.app/deploy/">relevant config</a>');
|
||||
throw new ConfigNotFoundError('Discourse RSS is disabled due to the lack of <a href="https://docs.rsshub.app/deploy/">relevant config</a>');
|
||||
}
|
||||
return config.discourse.config[ctx.req.param('configId')];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ import { load } from 'cheerio';
|
|||
import iconv from 'iconv-lite';
|
||||
import { parseDate } from '@/utils/parse-date';
|
||||
import { config } from '@/config';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
function fixUrl(itemLink, baseUrl) {
|
||||
// 处理相对链接
|
||||
|
|
@ -68,7 +70,7 @@ async function handler(ctx) {
|
|||
|
||||
const cookie = cid === undefined ? '' : config.discuz.cookies[cid];
|
||||
if (cookie === undefined) {
|
||||
throw new Error('缺少对应论坛的cookie.');
|
||||
throw new ConfigNotFoundError('缺少对应论坛的cookie.');
|
||||
}
|
||||
|
||||
const header = {
|
||||
|
|
@ -149,7 +151,7 @@ async function handler(ctx) {
|
|||
)
|
||||
);
|
||||
} else {
|
||||
throw new Error('不支持当前Discuz版本.');
|
||||
throw new InvalidParameterError('不支持当前Discuz版本.');
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
import { Route } from '@/types';
|
||||
import got from '@/utils/got';
|
||||
import { load } from 'cheerio';
|
||||
|
|
@ -141,7 +142,7 @@ async function handler(ctx) {
|
|||
const info = infos[ctx.req.param('type')];
|
||||
// 判断参数是否合理
|
||||
if (info === undefined) {
|
||||
throw new Error('不支持指定类型!');
|
||||
throw new InvalidParameterError('不支持指定类型!');
|
||||
}
|
||||
if (ctx.req.param('free') !== undefined) {
|
||||
info.params.is_free = 1;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { Route } from '@/types';
|
|||
import got from '@/utils/got';
|
||||
import { load } from 'cheerio';
|
||||
import { parseDate } from '@/utils/parse-date';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
const host = 'https://www.dlsite.com';
|
||||
const infos = {
|
||||
|
|
@ -75,7 +76,7 @@ async function handler(ctx) {
|
|||
const info = infos[ctx.req.param('type')];
|
||||
// 判断参数是否合理
|
||||
if (info === undefined) {
|
||||
throw new Error('不支持指定类型!');
|
||||
throw new InvalidParameterError('不支持指定类型!');
|
||||
}
|
||||
|
||||
const link = info.url.slice(1);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { config } from '@/config';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
|
||||
const defaultDomain = 'mp4us.com';
|
||||
|
||||
|
|
@ -87,7 +88,7 @@ function decodeCipherText(p, a, c, k, e, d) {
|
|||
function ensureDomain(ctx, domain = defaultDomain) {
|
||||
const origin = `https://${domain}`;
|
||||
if (!config.feature.allow_user_supply_unsafe_domain && !allowedDomains.has(new URL(origin).hostname)) {
|
||||
throw new Error(`This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.`);
|
||||
throw new ConfigNotFoundError(`This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.`);
|
||||
}
|
||||
return origin;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { config } from '@/config';
|
|||
import { fallback, queryToBoolean } from '@/utils/readable-social';
|
||||
import { templates, resolveUrl, proxyVideo, getOriginAvatar } from './utils';
|
||||
import puppeteer from '@/utils/puppeteer';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/hashtag/:cid/:routeParams?',
|
||||
|
|
@ -34,7 +35,7 @@ export const route: Route = {
|
|||
async function handler(ctx) {
|
||||
const cid = ctx.req.param('cid');
|
||||
if (isNaN(cid)) {
|
||||
throw new TypeError('Invalid tag ID. Tag ID should be a number.');
|
||||
throw new InvalidParameterError('Invalid tag ID. Tag ID should be a number.');
|
||||
}
|
||||
const routeParams = Object.fromEntries(new URLSearchParams(ctx.req.param('routeParams')));
|
||||
const embed = fallback(undefined, queryToBoolean(routeParams.embed), false); // embed video
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { config } from '@/config';
|
|||
import { getOriginAvatar } from './utils';
|
||||
import logger from '@/utils/logger';
|
||||
import puppeteer from '@/utils/puppeteer';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/live/:rid',
|
||||
|
|
@ -31,7 +32,7 @@ export const route: Route = {
|
|||
async function handler(ctx) {
|
||||
const rid = ctx.req.param('rid');
|
||||
if (isNaN(rid)) {
|
||||
throw new TypeError('Invalid room ID. Room ID should be a number.');
|
||||
throw new InvalidParameterError('Invalid room ID. Room ID should be a number.');
|
||||
}
|
||||
|
||||
const pageUrl = `https://live.douyin.com/${rid}`;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { art } from '@/utils/render';
|
|||
import { config } from '@/config';
|
||||
import { fallback, queryToBoolean } from '@/utils/readable-social';
|
||||
import { templates, resolveUrl, proxyVideo, getOriginAvatar, universalGet } from './utils';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/user/:uid/:routeParams?',
|
||||
|
|
@ -33,7 +34,7 @@ export const route: Route = {
|
|||
async function handler(ctx) {
|
||||
const uid = ctx.req.param('uid');
|
||||
if (!uid.startsWith('MS4wLjABAAAA')) {
|
||||
throw new Error('Invalid UID. UID should start with <b>MS4wLjABAAAA</b>.');
|
||||
throw new InvalidParameterError('Invalid UID. UID should start with <b>MS4wLjABAAAA</b>.');
|
||||
}
|
||||
const routeParams = Object.fromEntries(new URLSearchParams(ctx.req.param('routeParams')));
|
||||
const embed = fallback(undefined, queryToBoolean(routeParams.embed), false); // embed video
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { parseDate } from '@/utils/parse-date';
|
|||
import defaults from './defaults';
|
||||
import shortcuts from './shortcuts';
|
||||
import { isValidHost } from '@/utils/valid-host';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
export const route: Route = {
|
||||
path: ['/*/*', '/:0?'],
|
||||
|
|
@ -17,7 +18,7 @@ export const route: Route = {
|
|||
async function handler(ctx) {
|
||||
const site = ctx.params[0] ?? 'news';
|
||||
if (!isValidHost(site)) {
|
||||
throw new Error('Invalid site');
|
||||
throw new InvalidParameterError('Invalid site');
|
||||
}
|
||||
|
||||
let items;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import got from '@/utils/got';
|
|||
import { load } from 'cheerio';
|
||||
import { parseDate } from '@/utils/parse-date';
|
||||
import { isValidHost } from '@/utils/valid-host';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
const cateList = new Set(['all', 'design-resources', 'learn-design', 'inside-eagle']);
|
||||
|
||||
export const route: Route = {
|
||||
|
|
@ -35,7 +36,7 @@ async function handler(ctx) {
|
|||
let cate = ctx.req.param('cate') ?? 'all';
|
||||
let language = ctx.req.param('language') ?? 'cn';
|
||||
if (!isValidHost(cate) || !isValidHost(language)) {
|
||||
throw new Error('Invalid host');
|
||||
throw new InvalidParameterError('Invalid host');
|
||||
}
|
||||
if (!cateList.has(cate)) {
|
||||
language = cate;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { Route } from '@/types';
|
||||
import cache from '@/utils/cache';
|
||||
import EhAPI from './ehapi';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/favorites/:favcat?/:order?/:page?/:routeParams?',
|
||||
|
|
@ -22,7 +23,7 @@ export const route: Route = {
|
|||
|
||||
async function handler(ctx) {
|
||||
if (!EhAPI.has_cookie) {
|
||||
throw new Error('Ehentai favorites RSS is disabled due to the lack of <a href="https://docs.rsshub.app/deploy/config#route-specific-configurations">relevant config</a>');
|
||||
throw new ConfigNotFoundError('Ehentai favorites RSS is disabled due to the lack of <a href="https://docs.rsshub.app/deploy/config#route-specific-configurations">relevant config</a>');
|
||||
}
|
||||
const favcat = ctx.req.param('favcat') ? Number.parseInt(ctx.req.param('favcat')) : 0;
|
||||
const page = ctx.req.param('page');
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import { load } from 'cheerio';
|
|||
import { parseDate } from '@/utils/parse-date';
|
||||
import { art } from '@/utils/render';
|
||||
import path from 'node:path';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
const allowRegion = new Set(['tw', 'hk']);
|
||||
|
||||
export const route: Route = {
|
||||
|
|
@ -37,7 +38,7 @@ export const route: Route = {
|
|||
async function handler(ctx) {
|
||||
const region = ctx.req.param('region') ?? 'tw';
|
||||
if (!allowRegion.has(region)) {
|
||||
throw new Error('Invalid region');
|
||||
throw new InvalidParameterError('Invalid region');
|
||||
}
|
||||
|
||||
const feed = await parser.parseURL(`https://www.eprice.com.${region}/news/rss.xml`);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ const __dirname = getCurrentPath(import.meta.url);
|
|||
import got from '@/utils/got';
|
||||
import path from 'node:path';
|
||||
import { art } from '@/utils/render';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
const apiBaseUrl = 'https://apiv3.fansly.com';
|
||||
const baseUrl = 'https://fansly.com';
|
||||
|
|
@ -27,7 +28,7 @@ const getAccountByUsername = (username, tryGet) =>
|
|||
});
|
||||
|
||||
if (!accountResponse.response.length) {
|
||||
throw new Error('This profile or page does not exist.');
|
||||
throw new InvalidParameterError('This profile or page does not exist.');
|
||||
}
|
||||
|
||||
return accountResponse.response[0];
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import { parseDate } from '@/utils/parse-date';
|
|||
import { art } from '@/utils/render';
|
||||
import path from 'node:path';
|
||||
import { isValidHost } from '@/utils/valid-host';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
export const route: Route = {
|
||||
path: ['/global/:lang/:type?', '/ff14_global/:lang/:type?'],
|
||||
|
|
@ -41,7 +42,7 @@ async function handler(ctx) {
|
|||
const type = ctx.req.param('type') ?? 'all';
|
||||
|
||||
if (!isValidHost(lang)) {
|
||||
throw new Error('Invalid lang');
|
||||
throw new InvalidParameterError('Invalid lang');
|
||||
}
|
||||
|
||||
const response = await got({
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import got from '@/utils/got';
|
|||
import { load } from 'cheerio';
|
||||
import timezone from '@/utils/timezone';
|
||||
import { parseDate } from '@/utils/parse-date';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
const categories = {
|
||||
news: 0,
|
||||
|
|
@ -41,7 +42,7 @@ async function handler(ctx) {
|
|||
const limit = ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit'), 10) : 200;
|
||||
|
||||
if (!Object.hasOwn(categories, category.toLowerCase())) {
|
||||
throw new Error(`No category '${category}'.`);
|
||||
throw new InvalidParameterError(`No category '${category}'.`);
|
||||
}
|
||||
|
||||
const rootUrl = 'https://finviz.com';
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import got from '@/utils/got';
|
|||
import { load } from 'cheerio';
|
||||
import parser from '@/utils/rss-parser';
|
||||
import { isValidHost } from '@/utils/valid-host';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/:domain/:category?',
|
||||
|
|
@ -15,7 +16,7 @@ export const route: Route = {
|
|||
async function handler(ctx) {
|
||||
const { domain = 'news', category } = ctx.req.param();
|
||||
if (!isValidHost(domain)) {
|
||||
throw new Error('Invalid domain');
|
||||
throw new InvalidParameterError('Invalid domain');
|
||||
}
|
||||
const baseUrl = `https://${domain}.gamme.com.tw`;
|
||||
const feed = await parser.parseURL(`${baseUrl + (category ? `/category/${category}` : '')}/feed`);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import got from '@/utils/got';
|
|||
import { load } from 'cheerio';
|
||||
import { parseDate } from '@/utils/parse-date';
|
||||
import { isValidHost } from '@/utils/valid-host';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/:domain/tag/:tag',
|
||||
|
|
@ -15,7 +16,7 @@ export const route: Route = {
|
|||
async function handler(ctx) {
|
||||
const { domain = 'news', tag } = ctx.req.param();
|
||||
if (!isValidHost(domain)) {
|
||||
throw new Error('Invalid domain');
|
||||
throw new InvalidParameterError('Invalid domain');
|
||||
}
|
||||
const baseUrl = `https://${domain}.gamme.com.tw`;
|
||||
const pageUrl = `${baseUrl}/tag/${tag}`;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
import { Route } from '@/types';
|
||||
import cache from '@/utils/cache';
|
||||
import got from '@/utils/got';
|
||||
|
|
@ -60,7 +61,7 @@ async function handler(ctx) {
|
|||
list = list.get();
|
||||
|
||||
if (list.length > 0 && list.every((item) => item.url === undefined)) {
|
||||
throw new Error('Article URL not found! Please submit an issue on GitHub.');
|
||||
throw new InvalidParameterError('Article URL not found! Please submit an issue on GitHub.');
|
||||
}
|
||||
|
||||
const out = await Promise.all(
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
import { Route } from '@/types';
|
||||
import cache from '@/utils/cache';
|
||||
import got from '@/utils/got';
|
||||
|
|
@ -52,7 +53,7 @@ async function handler(ctx) {
|
|||
.get();
|
||||
|
||||
if (list.length > 0 && list.every((item) => item.url === undefined)) {
|
||||
throw new Error('Article URL not found! Please submit an issue on GitHub.');
|
||||
throw new InvalidParameterError('Article URL not found! Please submit an issue on GitHub.');
|
||||
}
|
||||
|
||||
const out = await Promise.all(
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { Route } from '@/types';
|
||||
import got from '@/utils/got';
|
||||
import { config } from '@/config';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/user/followers/:user',
|
||||
|
|
@ -27,7 +28,7 @@ export const route: Route = {
|
|||
|
||||
async function handler(ctx) {
|
||||
if (!config.github || !config.github.access_token) {
|
||||
throw new Error('GitHub follower RSS is disabled due to the lack of <a href="https://docs.rsshub.app/deploy/config#route-specific-configurations">relevant config</a>');
|
||||
throw new ConfigNotFoundError('GitHub follower RSS is disabled due to the lack of <a href="https://docs.rsshub.app/deploy/config#route-specific-configurations">relevant config</a>');
|
||||
}
|
||||
const user = ctx.req.param('user');
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { parseDate } from '@/utils/parse-date';
|
|||
|
||||
const apiUrl = 'https://api.github.com';
|
||||
import { config } from '@/config';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/notifications',
|
||||
|
|
@ -36,7 +37,7 @@ export const route: Route = {
|
|||
|
||||
async function handler(ctx) {
|
||||
if (!config.github || !config.github.access_token) {
|
||||
throw new Error('GitHub trending RSS is disabled due to the lack of <a href="https://docs.rsshub.app/deploy/config#route-specific-configurations">relevant config</a>');
|
||||
throw new ConfigNotFoundError('GitHub trending RSS is disabled due to the lack of <a href="https://docs.rsshub.app/deploy/config#route-specific-configurations">relevant config</a>');
|
||||
}
|
||||
const headers = {
|
||||
Accept: 'application/vnd.github.v3+json',
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { Route } from '@/types';
|
||||
import got from '@/utils/got';
|
||||
import { config } from '@/config';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/stars/:user/:repo',
|
||||
|
|
@ -27,7 +28,7 @@ export const route: Route = {
|
|||
|
||||
async function handler(ctx) {
|
||||
if (!config.github || !config.github.access_token) {
|
||||
throw new Error('GitHub star RSS is disabled due to the lack of <a href="https://docs.rsshub.app/deploy/config#route-specific-configurations">relevant config</a>');
|
||||
throw new ConfigNotFoundError('GitHub star RSS is disabled due to the lack of <a href="https://docs.rsshub.app/deploy/config#route-specific-configurations">relevant config</a>');
|
||||
}
|
||||
const user = ctx.req.param('user');
|
||||
const repo = ctx.req.param('repo');
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import got from '@/utils/got';
|
|||
import { art } from '@/utils/render';
|
||||
import { load } from 'cheerio';
|
||||
import path from 'node:path';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/trending/:since/:language/:spoken_language?',
|
||||
|
|
@ -44,7 +45,7 @@ export const route: Route = {
|
|||
|
||||
async function handler(ctx) {
|
||||
if (!config.github || !config.github.access_token) {
|
||||
throw new Error('GitHub trending RSS is disabled due to the lack of <a href="https://docs.rsshub.app/deploy/config#route-specific-configurations">relevant config</a>');
|
||||
throw new ConfigNotFoundError('GitHub trending RSS is disabled due to the lack of <a href="https://docs.rsshub.app/deploy/config#route-specific-configurations">relevant config</a>');
|
||||
}
|
||||
const since = ctx.req.param('since');
|
||||
const language = ctx.req.param('language') === 'any' ? '' : ctx.req.param('language');
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import { config } from '@/config';
|
|||
import { art } from '@/utils/render';
|
||||
import path from 'node:path';
|
||||
import { parseDate } from '@/utils/parse-date';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
|
||||
const titleMap = {
|
||||
date: 'Newest',
|
||||
|
|
@ -52,7 +53,7 @@ async function handler(ctx) {
|
|||
|
||||
const API_KEY = config.google.fontsApiKey;
|
||||
if (!API_KEY) {
|
||||
throw new Error('Google Fonts API key is required.');
|
||||
throw new ConfigNotFoundError('Google Fonts API key is required.');
|
||||
}
|
||||
|
||||
const googleFontsAPI = `https://www.googleapis.com/webfonts/v1/webfonts?sort=${sort}&key=${API_KEY}`;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import got from '@/utils/got';
|
|||
import { load } from 'cheerio';
|
||||
import { parseDate } from '@/utils/parse-date';
|
||||
import timezone from '@/utils/timezone';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
const rootUrl = 'http://www.sz.gov.cn/cn/xxgk/zfxxgj/';
|
||||
|
||||
const config = {
|
||||
|
|
@ -49,7 +50,7 @@ export const route: Route = {
|
|||
async function handler(ctx) {
|
||||
const cfg = config[ctx.req.param('caty')];
|
||||
if (!cfg) {
|
||||
throw new Error('Bad category. See <a href="https://docs.rsshub.app/routes/government#guang-dong-sheng-ren-min-zheng-fu-guang-dong-sheng-shen-zhen-shi-ren-min-zheng-fu">docs</a>');
|
||||
throw new InvalidParameterError('Bad category. See <a href="https://docs.rsshub.app/routes/government#guang-dong-sheng-ren-min-zheng-fu-guang-dong-sheng-shen-zhen-shi-ren-min-zheng-fu">docs</a>');
|
||||
}
|
||||
|
||||
const currentUrl = new URL(cfg.link, rootUrl).href;
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import got from '@/utils/got';
|
|||
import { load } from 'cheerio';
|
||||
import { parseDate } from '@/utils/parse-date';
|
||||
import timezone from '@/utils/timezone';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
const config = {
|
||||
tzgg: {
|
||||
|
|
@ -41,7 +42,7 @@ async function handler(ctx) {
|
|||
const baseUrl = 'http://zjj.sz.gov.cn/xxgk/';
|
||||
const cfg = config[ctx.req.param('caty')];
|
||||
if (!cfg) {
|
||||
throw new Error('Bad category. See <a href="https://docs.rsshub.app/routes/government#guang-dong-sheng-ren-min-zheng-fu-shen-zhen-shi-zhu-fang-he-jian-she-ju">docs</a>');
|
||||
throw new InvalidParameterError('Bad category. See <a href="https://docs.rsshub.app/routes/government#guang-dong-sheng-ren-min-zheng-fu-shen-zhen-shi-zhu-fang-he-jian-she-ju">docs</a>');
|
||||
}
|
||||
|
||||
const currentUrl = new URL(cfg.link, baseUrl).href;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import got from '@/utils/got';
|
|||
import { load } from 'cheerio';
|
||||
import { parseDate } from '@/utils/parse-date';
|
||||
import timezone from '@/utils/timezone';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/suzhou/news/:uid',
|
||||
|
|
@ -119,7 +120,7 @@ async function handler(ctx) {
|
|||
title = '苏州市政府 - 民生资讯';
|
||||
break;
|
||||
default:
|
||||
throw new Error('pattern not matched');
|
||||
throw new InvalidParameterError('pattern not matched');
|
||||
}
|
||||
if (apiUrl) {
|
||||
const response = await got(apiUrl);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import { load } from 'cheerio';
|
|||
import { art } from '@/utils/render';
|
||||
import path from 'node:path';
|
||||
import { isValidHost } from '@/utils/valid-host';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/:username/:products',
|
||||
|
|
@ -31,7 +32,7 @@ async function handler(ctx) {
|
|||
const username = ctx.req.param('username');
|
||||
const products = ctx.req.param('products');
|
||||
if (!isValidHost(username)) {
|
||||
throw new Error('Invalid username');
|
||||
throw new InvalidParameterError('Invalid username');
|
||||
}
|
||||
const url = `https://${username}.gumroad.com/l/${products}`;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { Route } from '@/types';
|
||||
import got from '@/utils/got';
|
||||
import { parseList, parseItem } from './utils';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
const channelMap = {
|
||||
calendar: 'pac',
|
||||
|
|
@ -42,7 +43,7 @@ async function handler(ctx) {
|
|||
const result = parseList(response.result);
|
||||
|
||||
if (result.length === 0) {
|
||||
throw new Error('Unknown channel');
|
||||
throw new InvalidParameterError('Unknown channel');
|
||||
}
|
||||
|
||||
const channelName = result[0].channels[0].name;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import got from '@/utils/got';
|
|||
import { load } from 'cheerio';
|
||||
import { parseDate } from '@/utils/parse-date';
|
||||
import { isValidHost } from '@/utils/valid-host';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
function getKeysRecursive(dic, key, attr, array) {
|
||||
for (const v of Object.values(dic)) {
|
||||
|
|
@ -46,7 +47,7 @@ export const route: Route = {
|
|||
async function handler(ctx) {
|
||||
const category = ctx.req.param('category') ?? 'china';
|
||||
if (!isValidHost(category)) {
|
||||
throw new Error('Invalid category');
|
||||
throw new InvalidParameterError('Invalid category');
|
||||
}
|
||||
|
||||
const host = `https://${category}.huanqiu.com`;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { ig, login } from './utils';
|
|||
import logger from '@/utils/logger';
|
||||
import { config } from '@/config';
|
||||
import { renderItems } from '../common-utils';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
// loadContent pulls the desired user/tag/etc
|
||||
async function loadContent(category, nameOrId, tryGet) {
|
||||
|
|
@ -93,7 +94,7 @@ async function handler(ctx) {
|
|||
// e.g. username for user feed
|
||||
const { category, key } = ctx.req.param();
|
||||
if (!availableCategories.includes(category)) {
|
||||
throw new Error('Such feed is not supported.');
|
||||
throw new InvalidParameterError('Such feed is not supported.');
|
||||
}
|
||||
|
||||
if (config.instagram && config.instagram.proxy) {
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
import { IgApiClient } from 'instagram-private-api';
|
||||
import logger from '@/utils/logger';
|
||||
import { config } from '@/config';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
|
||||
const ig = new IgApiClient();
|
||||
|
||||
async function login(ig, cache) {
|
||||
if (!config.instagram || !config.instagram.username || !config.instagram.password) {
|
||||
throw new Error('Instagram RSS is disabled due to the lack of <a href="https://docs.rsshub.app/deploy/config#route-specific-configurations">relevant config</a>');
|
||||
throw new ConfigNotFoundError('Instagram RSS is disabled due to the lack of <a href="https://docs.rsshub.app/deploy/config#route-specific-configurations">relevant config</a>');
|
||||
}
|
||||
const LOGIN_CACHE_KEY = 'instagram:login';
|
||||
const { username, password } = config.instagram;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ import { CookieJar } from 'tough-cookie';
|
|||
import { config } from '@/config';
|
||||
import { renderItems } from '../common-utils';
|
||||
import { baseUrl, COOKIE_URL, checkLogin, getUserInfo, getUserFeedItems, getTagsFeedItems, getLoggedOutTagsFeedItems, renderGuestItems } from './utils';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/2/:category/:key',
|
||||
|
|
@ -39,7 +41,7 @@ async function handler(ctx) {
|
|||
const { category, key } = ctx.req.param();
|
||||
const { cookie } = config.instagram;
|
||||
if (!availableCategories.includes(category)) {
|
||||
throw new Error('Such feed is not supported.');
|
||||
throw new InvalidParameterError('Such feed is not supported.');
|
||||
}
|
||||
|
||||
let cookieJar = await cache.get('instagram:cookieJar');
|
||||
|
|
@ -58,7 +60,7 @@ async function handler(ctx) {
|
|||
}
|
||||
|
||||
if (!wwwClaimV2 && cookie && !(await checkLogin(cookieJar, cache))) {
|
||||
throw new Error('Invalid cookie');
|
||||
throw new ConfigNotFoundError('Invalid cookie');
|
||||
}
|
||||
|
||||
let feedTitle, feedLink, feedDescription, feedLogo;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { parseDate } from '@/utils/parse-date';
|
|||
import { config } from '@/config';
|
||||
import { art } from '@/utils/render';
|
||||
import path from 'node:path';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
|
||||
const baseUrl = 'https://www.instagram.com';
|
||||
const COOKIE_URL = 'https://instagram.com';
|
||||
|
|
@ -59,7 +60,7 @@ const getUserInfo = async (username, cookieJar, cache) => {
|
|||
},
|
||||
});
|
||||
if (response.url.includes('/accounts/login/')) {
|
||||
throw new Error('Invalid cookie');
|
||||
throw new ConfigNotFoundError('Invalid cookie');
|
||||
}
|
||||
|
||||
webProfileInfo = response.data.data.user;
|
||||
|
|
@ -69,7 +70,7 @@ const getUserInfo = async (username, cookieJar, cache) => {
|
|||
await cache.set(`instagram:userInfo:${id}`, webProfileInfo);
|
||||
} catch (error) {
|
||||
if (error.message.includes("Cookie not in this host's domain")) {
|
||||
throw new Error('Invalid cookie');
|
||||
throw new ConfigNotFoundError('Invalid cookie');
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
|
|
@ -97,7 +98,7 @@ const getUserFeedItems = (id, username, cookieJar, cache) =>
|
|||
},
|
||||
});
|
||||
if (response.url.includes('/accounts/login/')) {
|
||||
throw new Error(`Invalid cookie.
|
||||
throw new ConfigNotFoundError(`Invalid cookie.
|
||||
Please also check if your account is being blocked by Instagram.`);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import { load } from 'cheerio';
|
|||
import { parseDate } from '@/utils/parse-date';
|
||||
import { art } from '@/utils/render';
|
||||
import path from 'node:path';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/album/:id',
|
||||
|
|
@ -43,7 +44,7 @@ async function handler(ctx) {
|
|||
} = await got(`https://pcw-api.iqiyi.com/album/album/baseinfo/${album.videoAlbumInfo.albumId}`);
|
||||
|
||||
if (Object.keys(album.cacheAlbumList).length === 0) {
|
||||
throw new Error(`${baseInfo.name} is not available in this server region.`);
|
||||
throw new InvalidParameterError(`${baseInfo.name} is not available in this server region.`);
|
||||
}
|
||||
|
||||
let pos = 1;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { parseDate } from '@/utils/parse-date';
|
|||
import { art } from '@/utils/render';
|
||||
import path from 'node:path';
|
||||
import { isValidHost } from '@/utils/valid-host';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/devlog/:user/:id',
|
||||
|
|
@ -38,7 +39,7 @@ async function handler(ctx) {
|
|||
const user = ctx.req.param('user') ?? '';
|
||||
const id = ctx.req.param('id') ?? '';
|
||||
if (!isValidHost(user)) {
|
||||
throw new Error('Invalid user');
|
||||
throw new InvalidParameterError('Invalid user');
|
||||
}
|
||||
|
||||
const rootUrl = `https://${user}.itch.io/${id}/devlog`;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
import { Route } from '@/types';
|
||||
import cache from '@/utils/cache';
|
||||
import got from '@/utils/got';
|
||||
|
|
@ -59,7 +60,7 @@ export const route: Route = {
|
|||
async function handler(ctx) {
|
||||
const cfg = config[ctx.req.param('caty')];
|
||||
if (!cfg) {
|
||||
throw new Error('Bad category. See <a href="https://docs.rsshub.app/routes/new-media#it-zhi-jia">https://docs.rsshub.app/routes/new-media#it-zhi-jia</a>');
|
||||
throw new InvalidParameterError('Bad category. See <a href="https://docs.rsshub.app/routes/new-media#it-zhi-jia">https://docs.rsshub.app/routes/new-media#it-zhi-jia</a>');
|
||||
}
|
||||
|
||||
const current_url = get_url(ctx.req.param('caty'));
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
import { Route } from '@/types';
|
||||
import cache from '@/utils/cache';
|
||||
import got from '@/utils/got';
|
||||
|
|
@ -49,7 +50,7 @@ async function handler(ctx) {
|
|||
const id = type2id[option];
|
||||
|
||||
if (!id) {
|
||||
throw new Error('Bad type. See <a href="https://docs.rsshub.app/routes/new-media#it-zhi-jia">https://docs.rsshub.app/routes/new-media#it-zhi-jia</a>');
|
||||
throw new InvalidParameterError('Bad type. See <a href="https://docs.rsshub.app/routes/new-media#it-zhi-jia">https://docs.rsshub.app/routes/new-media#it-zhi-jia</a>');
|
||||
}
|
||||
|
||||
const list = $(`#${id} > li`)
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import { art } from '@/utils/render';
|
|||
import { parseDate } from '@/utils/parse-date';
|
||||
import path from 'node:path';
|
||||
import MarkdownIt from 'markdown-it';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
const md = MarkdownIt({
|
||||
html: true,
|
||||
});
|
||||
|
|
@ -51,7 +52,7 @@ export const route: Route = {
|
|||
|
||||
async function handler() {
|
||||
if (!config.iwara || !config.iwara.username || !config.iwara.password) {
|
||||
throw new Error('Iwara subscription RSS is disabled due to the lack of <a href="https://docs.rsshub.app/deploy/config#route-specific-configurations">relevant config</a>');
|
||||
throw new ConfigNotFoundError('Iwara subscription RSS is disabled due to the lack of <a href="https://docs.rsshub.app/deploy/config#route-specific-configurations">relevant config</a>');
|
||||
}
|
||||
|
||||
const rootUrl = `https://www.iwara.tv`;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { parseDate } from '@/utils/parse-date';
|
|||
import { art } from '@/utils/render';
|
||||
import path from 'node:path';
|
||||
import { config } from '@/config';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
|
||||
const toSize = (raw) => {
|
||||
const matches = raw.match(/(\d+(\.\d+)?)(\w+)/);
|
||||
|
|
@ -41,7 +42,7 @@ async function handler(ctx) {
|
|||
const westernUrl = `https://www.${westernDomain}`;
|
||||
|
||||
if (!config.feature.allow_user_supply_unsafe_domain && (!allowDomain.has(new URL(`https://${domain}/`).hostname) || !allowDomain.has(new URL(`https://${westernDomain}/`).hostname))) {
|
||||
throw new Error(`This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.`);
|
||||
throw new ConfigNotFoundError(`This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.`);
|
||||
}
|
||||
|
||||
const currentUrl = `${isWestern ? westernUrl : rootUrl}${getSubPath(ctx)
|
||||
|
|
|
|||
|
|
@ -3,13 +3,14 @@ import got from '@/utils/got';
|
|||
import { load } from 'cheerio';
|
||||
import { parseDate } from '@/utils/parse-date';
|
||||
import { config } from '@/config';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
const allowDomain = new Set(['javdb.com', 'javdb36.com', 'javdb007.com', 'javdb521.com']);
|
||||
|
||||
const ProcessItems = async (ctx, currentUrl, title) => {
|
||||
const domain = ctx.req.query('domain') ?? 'javdb.com';
|
||||
const url = new URL(currentUrl, `https://${domain}`);
|
||||
if (!config.feature.allow_user_supply_unsafe_domain && !allowDomain.has(url.hostname)) {
|
||||
throw new Error(`This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.`);
|
||||
throw new ConfigNotFoundError(`This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.`);
|
||||
}
|
||||
|
||||
const rootUrl = `https://${domain}`;
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ import timezone from '@/utils/timezone';
|
|||
import { parseDate } from '@/utils/parse-date';
|
||||
import { art } from '@/utils/render';
|
||||
import path from 'node:path';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
const resolveRelativeLink = (link, baseUrl) => (link.startsWith('http') ? link : `${baseUrl}${link}`);
|
||||
|
||||
|
|
@ -37,7 +39,7 @@ async function handler(ctx) {
|
|||
|
||||
// raise error for invalid languages
|
||||
if (!['china', 'tchina'].includes(language)) {
|
||||
throw new Error('Invalid language');
|
||||
throw new ConfigNotFoundError('Invalid language');
|
||||
}
|
||||
|
||||
const rootUrl = `https://${language}.kyodonews.net`;
|
||||
|
|
@ -47,7 +49,7 @@ async function handler(ctx) {
|
|||
try {
|
||||
response = await got(currentUrl);
|
||||
} catch (error) {
|
||||
throw error.response && error.response.statusCode === 404 ? new Error('Invalid keyword') : error;
|
||||
throw error.response && error.response.statusCode === 404 ? new InvalidParameterError('Invalid keyword') : error;
|
||||
}
|
||||
|
||||
const $ = load(response.data, { xmlMode: keyword === 'rss' });
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ import { parseDate } from '@/utils/parse-date';
|
|||
import MarkdownIt from 'markdown-it';
|
||||
const md = MarkdownIt({ html: true });
|
||||
import { config } from '@/config';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/:community/:sort?',
|
||||
|
|
@ -34,12 +36,12 @@ async function handler(ctx) {
|
|||
const community = ctx.req.param('community');
|
||||
const communitySlices = community.split('@');
|
||||
if (communitySlices.length !== 2) {
|
||||
throw new Error(`Invalid community: ${community}`);
|
||||
throw new InvalidParameterError(`Invalid community: ${community}`);
|
||||
}
|
||||
const instance = community.split('@')[1];
|
||||
const allowedDomain = ['lemmy.world', 'lemm.ee', 'lemmy.ml', 'sh.itjust.works', 'feddit.de', 'hexbear.net', 'beehaw.org', 'lemmynsfw.com', 'lemmy.ca', 'programming.dev'];
|
||||
if (!config.feature.allow_user_supply_unsafe_domain && !allowedDomain.includes(new URL(`http://${instance}/`).hostname)) {
|
||||
throw new Error(`This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.`);
|
||||
throw new ConfigNotFoundError(`This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.`);
|
||||
}
|
||||
|
||||
const communityUrl = `https://${instance}/api/v3/community?name=${community}`;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { Route } from '@/types';
|
|||
import got from '@/utils/got';
|
||||
import { load } from 'cheerio';
|
||||
import { isValidHost } from '@/utils/valid-host';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/:region?',
|
||||
|
|
@ -31,7 +32,7 @@ async function handler(ctx) {
|
|||
const region = ctx.req.param('region') ?? 'ukraine';
|
||||
const limit = ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit')) : 50;
|
||||
if (!isValidHost(region)) {
|
||||
throw new Error('Invalid region');
|
||||
throw new InvalidParameterError('Invalid region');
|
||||
}
|
||||
|
||||
const url = `https://${region}.liveuamap.com/`;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
import { Route } from '@/types';
|
||||
import got from '@/utils/got';
|
||||
import { parseDate } from '@/utils/parse-date';
|
||||
|
|
@ -25,7 +26,7 @@ async function handler(ctx) {
|
|||
const name = ctx.req.param('name') ?? 'i';
|
||||
const limit = ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit')) : '50';
|
||||
if (!isValidHost(name)) {
|
||||
throw new Error('Invalid name');
|
||||
throw new InvalidParameterError('Invalid name');
|
||||
}
|
||||
|
||||
const rootUrl = `${name}.lofter.com`;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import timezone from '@/utils/timezone';
|
|||
import { parseDate } from '@/utils/parse-date';
|
||||
import { art } from '@/utils/render';
|
||||
import path from 'node:path';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/:id?/:category{.+}?',
|
||||
|
|
@ -21,7 +22,7 @@ export const route: Route = {
|
|||
async function handler(ctx) {
|
||||
const { id = 'news', category = 'china' } = ctx.req.param();
|
||||
if (!isValidHost(id)) {
|
||||
throw new Error('Invalid id');
|
||||
throw new InvalidParameterError('Invalid id');
|
||||
}
|
||||
const limit = ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit'), 10) : 30;
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { config } from '@/config';
|
|||
import { simpleParser } from 'mailparser';
|
||||
import logger from '@/utils/logger';
|
||||
import { parseDate } from '@/utils/parse-date';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/imap/:email/:folder{.+}?',
|
||||
|
|
@ -23,7 +24,7 @@ async function handler(ctx) {
|
|||
};
|
||||
|
||||
if (!mailConfig.username || !mailConfig.password || !mailConfig.host || !mailConfig.port) {
|
||||
throw new Error('Email Inbox RSS is disabled due to the lack of <a href="https://docs.rsshub.app/deploy/#route-specific-configurations">relevant config</a>');
|
||||
throw new ConfigNotFoundError('Email Inbox RSS is disabled due to the lack of <a href="https://docs.rsshub.app/deploy/#route-specific-configurations">relevant config</a>');
|
||||
}
|
||||
|
||||
const client = new ImapFlow({
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { load } from 'cheerio';
|
|||
import { art } from '@/utils/render';
|
||||
import path from 'node:path';
|
||||
import { config } from '@/config';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
const web_url = 'https://www.manhuagui.com/user/book/shelf/1';
|
||||
|
||||
export const route: Route = {
|
||||
|
|
@ -45,7 +46,7 @@ export const route: Route = {
|
|||
|
||||
async function handler() {
|
||||
if (!config.manhuagui || !config.manhuagui.cookie) {
|
||||
throw new Error('manhuagui RSS is disabled due to the lack of <a href="https://docs.rsshub.app/deploy/config#route-specific-configurations">relevant config</a>');
|
||||
throw new ConfigNotFoundError('manhuagui RSS is disabled due to the lack of <a href="https://docs.rsshub.app/deploy/config#route-specific-configurations">relevant config</a>');
|
||||
}
|
||||
const cookie = config.manhuagui.cookie;
|
||||
const response = await got({
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { Route } from '@/types';
|
||||
import utils from './utils';
|
||||
import { config } from '@/config';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/account_id/:site/:account_id/statuses/:only_media?',
|
||||
|
|
@ -14,7 +15,7 @@ async function handler(ctx) {
|
|||
const account_id = ctx.req.param('account_id');
|
||||
const only_media = ctx.req.param('only_media') ? 'true' : 'false';
|
||||
if (!config.feature.allow_user_supply_unsafe_domain && !utils.allowSiteList.includes(site)) {
|
||||
throw new Error(`This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.`);
|
||||
throw new ConfigNotFoundError(`This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.`);
|
||||
}
|
||||
|
||||
const { account_data, data } = await utils.getAccountStatuses(site, account_id, only_media);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { Route } from '@/types';
|
|||
import got from '@/utils/got';
|
||||
import utils from './utils';
|
||||
import { config } from '@/config';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/timeline/:site/:only_media?',
|
||||
|
|
@ -26,7 +27,7 @@ async function handler(ctx) {
|
|||
const site = ctx.req.param('site');
|
||||
const only_media = ctx.req.param('only_media') ? 'true' : 'false';
|
||||
if (!config.feature.allow_user_supply_unsafe_domain && !utils.allowSiteList.includes(site)) {
|
||||
throw new Error(`This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.`);
|
||||
throw new ConfigNotFoundError(`This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.`);
|
||||
}
|
||||
|
||||
const url = `http://${site}/api/v1/timelines/public?local=true&only_media=${only_media}`;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { Route } from '@/types';
|
|||
import got from '@/utils/got';
|
||||
import utils from './utils';
|
||||
import { config } from '@/config';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/remote/:site/:only_media?',
|
||||
|
|
@ -26,7 +27,7 @@ async function handler(ctx) {
|
|||
const site = ctx.req.param('site');
|
||||
const only_media = ctx.req.param('only_media') ? 'true' : 'false';
|
||||
if (!config.feature.allow_user_supply_unsafe_domain && !utils.allowSiteList.includes(site)) {
|
||||
throw new Error(`This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.`);
|
||||
throw new ConfigNotFoundError(`This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.`);
|
||||
}
|
||||
|
||||
const url = `http://${site}/api/v1/timelines/public?remote=true&only_media=${only_media}`;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import cache from '@/utils/cache';
|
|||
import got from '@/utils/got';
|
||||
import { parseDate } from '@/utils/parse-date';
|
||||
import { config } from '@/config';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
|
||||
const allowSiteList = ['mastodon.social', 'pawoo.net', config.mastodon.apiHost].filter(Boolean);
|
||||
|
||||
|
|
@ -93,10 +94,10 @@ async function getAccountIdByAcct(acct) {
|
|||
const site = mastodonConfig.apiHost || acctHost;
|
||||
const acctDomain = mastodonConfig.acctDomain || acctHost;
|
||||
if (!(site && acctDomain)) {
|
||||
throw new Error('Mastodon RSS is disabled due to the lack of <a href="https://docs.rsshub.app/deploy/config#route-specific-configurations">relevant config</a>');
|
||||
throw new ConfigNotFoundError('Mastodon RSS is disabled due to the lack of <a href="https://docs.rsshub.app/deploy/config#route-specific-configurations">relevant config</a>');
|
||||
}
|
||||
if (!config.feature.allow_user_supply_unsafe_domain && !allowSiteList.includes(site)) {
|
||||
throw new Error(`RSS for this domain is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true' or 'MASTODON_API_HOST' is set.`);
|
||||
throw new ConfigNotFoundError(`RSS for this domain is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true' or 'MASTODON_API_HOST' is set.`);
|
||||
}
|
||||
|
||||
const search_url = `https://${site}/api/v2/search`;
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { config } from '@/config';
|
|||
|
||||
import parseArticle from './parse-article.js';
|
||||
import { getFollowingFeedQuery } from './graphql.js';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found.js';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/following/:user',
|
||||
|
|
@ -35,7 +36,7 @@ async function handler(ctx) {
|
|||
|
||||
const cookie = config.medium.cookies[user];
|
||||
if (cookie === undefined) {
|
||||
throw new Error(`缺少 Medium 用户 ${user} 登录后的 Cookie 值`);
|
||||
throw new ConfigNotFoundError(`缺少 Medium 用户 ${user} 登录后的 Cookie 值`);
|
||||
}
|
||||
|
||||
const posts = await getFollowingFeedQuery(user, cookie);
|
||||
|
|
@ -43,7 +44,7 @@ async function handler(ctx) {
|
|||
|
||||
if (!posts) {
|
||||
// login failed
|
||||
throw new Error(`Medium 用户 ${user} 的 Cookie 无效或已过期`);
|
||||
throw new ConfigNotFoundError(`Medium 用户 ${user} 的 Cookie 无效或已过期`);
|
||||
}
|
||||
|
||||
const urls = posts.items.map((data) => data.post.mediumUrl);
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { config } from '@/config';
|
|||
|
||||
import parseArticle from './parse-article.js';
|
||||
import { getWebInlineRecommendedFeedQuery } from './graphql.js';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found.js';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/for-you/:user',
|
||||
|
|
@ -35,7 +36,7 @@ async function handler(ctx) {
|
|||
|
||||
const cookie = config.medium.cookies[user];
|
||||
if (cookie === undefined) {
|
||||
throw new Error(`缺少 Medium 用户 ${user} 登录后的 Cookie 值`);
|
||||
throw new ConfigNotFoundError(`缺少 Medium 用户 ${user} 登录后的 Cookie 值`);
|
||||
}
|
||||
|
||||
const posts = await getWebInlineRecommendedFeedQuery(user, cookie);
|
||||
|
|
@ -43,7 +44,7 @@ async function handler(ctx) {
|
|||
|
||||
if (!posts) {
|
||||
// login failed
|
||||
throw new Error(`Medium 用户 ${user} 的 Cookie 无效或已过期`);
|
||||
throw new ConfigNotFoundError(`Medium 用户 ${user} 的 Cookie 无效或已过期`);
|
||||
}
|
||||
|
||||
const urls = posts.items.map((data) => data.post.mediumUrl);
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ import { config } from '@/config';
|
|||
|
||||
import parseArticle from './parse-article.js';
|
||||
import { getUserCatalogMainContentQuery } from './graphql.js';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found.js';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter.js';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/list/:user/:catalogId',
|
||||
|
|
@ -37,10 +39,10 @@ async function handler(ctx) {
|
|||
ctx.set('json', catalog);
|
||||
|
||||
if (catalog && catalog.__typename === 'Forbidden') {
|
||||
throw new Error(`无权访问 id 为 ${catalogId} 的 List(可能是未设置 Cookie 或 Cookie 已过期)`);
|
||||
throw new ConfigNotFoundError(`无权访问 id 为 ${catalogId} 的 List(可能是未设置 Cookie 或 Cookie 已过期)`);
|
||||
}
|
||||
if (!catalog || !catalog.itemsConnection) {
|
||||
throw new Error(`id 为 ${catalogId} 的 List 不存在`);
|
||||
throw new InvalidParameterError(`id 为 ${catalogId} 的 List 不存在`);
|
||||
}
|
||||
|
||||
const name = catalog.name;
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { config } from '@/config';
|
|||
|
||||
import parseArticle from './parse-article.js';
|
||||
import { getWebInlineTopicFeedQuery } from './graphql.js';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found.js';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/tag/:user/:tag',
|
||||
|
|
@ -38,7 +39,7 @@ async function handler(ctx) {
|
|||
|
||||
const cookie = config.medium.cookies[user];
|
||||
if (cookie === undefined) {
|
||||
throw new Error(`缺少 Medium 用户 ${user} 登录后的 Cookie 值`);
|
||||
throw new ConfigNotFoundError(`缺少 Medium 用户 ${user} 登录后的 Cookie 值`);
|
||||
}
|
||||
|
||||
const posts = await getWebInlineTopicFeedQuery(user, tag, cookie);
|
||||
|
|
@ -46,7 +47,7 @@ async function handler(ctx) {
|
|||
|
||||
if (!posts) {
|
||||
// login failed
|
||||
throw new Error(`Medium 用户 ${user} 的 Cookie 无效或已过期`);
|
||||
throw new ConfigNotFoundError(`Medium 用户 ${user} 的 Cookie 无效或已过期`);
|
||||
}
|
||||
|
||||
const urls = posts.items.map((data) => data.post.mediumUrl);
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
import cache from '@/utils/cache';
|
||||
import got from '@/utils/got';
|
||||
import { config } from '@/config';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
|
||||
const getUserFullInfo = (ctx, uid) => {
|
||||
if (!uid && !config.mihoyo.cookie) {
|
||||
throw new Error('GetUserFullInfo is not available due to the absense of [Miyoushe Cookie]. Check <a href="https://docs.rsshub.app/deploy/config#route-specific-configurations">relevant config tutorial</a>');
|
||||
throw new ConfigNotFoundError('GetUserFullInfo is not available due to the absense of [Miyoushe Cookie]. Check <a href="https://docs.rsshub.app/deploy/config#route-specific-configurations">relevant config tutorial</a>');
|
||||
}
|
||||
uid ||= '';
|
||||
const key = 'mihoyo:user-full-info-uid-' + uid;
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import got from '@/utils/got';
|
|||
import cache from './cache';
|
||||
import { config } from '@/config';
|
||||
import { post2item } from './utils';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/bbs/timeline',
|
||||
|
|
@ -37,7 +38,7 @@ export const route: Route = {
|
|||
|
||||
async function handler(ctx) {
|
||||
if (!config.mihoyo.cookie) {
|
||||
throw new Error('Miyoushe Timeline is not available due to the absense of [Miyoushe Cookie]. Check <a href="https://docs.rsshub.app/deploy/config#route-specific-configurations">relevant config tutorial</a>');
|
||||
throw new ConfigNotFoundError('Miyoushe Timeline is not available due to the absense of [Miyoushe Cookie]. Check <a href="https://docs.rsshub.app/deploy/config#route-specific-configurations">relevant config tutorial</a>');
|
||||
}
|
||||
|
||||
const page_size = ctx.req.query('limit') || '20';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { Route, Data } from '@/types';
|
||||
import got from '@/utils/got';
|
||||
import { config } from '@/config';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/entry/:feeds/:parameters?',
|
||||
|
|
@ -63,7 +64,7 @@ async function handler(ctx) {
|
|||
const token = config.miniflux.token;
|
||||
|
||||
if (!token) {
|
||||
throw new Error('This RSS feed is disabled due to its incorrect configuration: the token is missing.');
|
||||
throw new ConfigNotFoundError('This RSS feed is disabled due to its incorrect configuration: the token is missing.');
|
||||
}
|
||||
|
||||
// In this function, var`mark`, `link`, and `limit`, `addFeedName`
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { Route } from '@/types';
|
||||
import got from '@/utils/got';
|
||||
import { config } from '@/config';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/subscription/:parameters?',
|
||||
|
|
@ -43,7 +44,7 @@ async function handler(ctx) {
|
|||
const token = config.miniflux.token;
|
||||
|
||||
if (!token) {
|
||||
throw new Error('This RSS feed is disabled due to its incorrect configuration: the token is missing.');
|
||||
throw new ConfigNotFoundError('This RSS feed is disabled due to its incorrect configuration: the token is missing.');
|
||||
}
|
||||
|
||||
function set(item) {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ const md = MarkdownIt({
|
|||
linkify: true,
|
||||
});
|
||||
import { isValidHost } from '@/utils/valid-host';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/:id',
|
||||
|
|
@ -29,7 +30,7 @@ export const route: Route = {
|
|||
async function handler(ctx) {
|
||||
const id = ctx.req.param('id');
|
||||
if (!id.endsWith('.eth') && !isValidHost(id)) {
|
||||
throw new Error('Invalid id');
|
||||
throw new InvalidParameterError('Invalid id');
|
||||
}
|
||||
const rootUrl = 'https://mirror.xyz';
|
||||
const currentUrl = id.endsWith('.eth') ? `${rootUrl}/${id}` : `https://${id}.mirror.xyz`;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { Route } from '@/types';
|
|||
import got from '@/utils/got';
|
||||
import utils from './utils';
|
||||
import { config } from '@/config';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/notes/featured/:site',
|
||||
|
|
@ -24,7 +25,7 @@ export const route: Route = {
|
|||
async function handler(ctx) {
|
||||
const site = ctx.req.param('site');
|
||||
if (!config.feature.allow_user_supply_unsafe_domain && !utils.allowSiteList.includes(site)) {
|
||||
throw new Error(`This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.`);
|
||||
throw new ConfigNotFoundError(`This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.`);
|
||||
}
|
||||
|
||||
// docs on: https://misskey-hub.net/docs/api/endpoints/notes/featured.html
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import got from '@/utils/got';
|
|||
import CryptoJS from 'crypto-js';
|
||||
import { parseDate } from '@/utils/parse-date';
|
||||
import { queries } from './queries';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/:username/:type?',
|
||||
|
|
@ -37,7 +38,7 @@ async function handler(ctx) {
|
|||
|
||||
const type = ctx.req.param('type') ?? 'uploads';
|
||||
if (!['stream', 'uploads', 'favorites', 'listens'].includes(type)) {
|
||||
throw new Error(`Invalid type: ${type}`);
|
||||
throw new InvalidParameterError(`Invalid type: ${type}`);
|
||||
}
|
||||
const username = ctx.req.param('username');
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import { parseDate } from '@/utils/parse-date';
|
|||
import { art } from '@/utils/render';
|
||||
import path from 'node:path';
|
||||
import { isValidHost } from '@/utils/valid-host';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/activity/:category?/:language?/:latestAdditions?/:latestEdits?/:latestAlerts?/:latestPictures?',
|
||||
|
|
@ -75,7 +76,7 @@ async function handler(ctx) {
|
|||
const latestPictures = ctx.req.param('latestPictures') ?? '1';
|
||||
|
||||
if (language && !isValidHost(language)) {
|
||||
throw new Error('Invalid language');
|
||||
throw new InvalidParameterError('Invalid language');
|
||||
}
|
||||
|
||||
const rootUrl = `https://${language === 'en' || language === '' ? '' : `${language}.`}myfigurecollection.net`;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { load } from 'cheerio';
|
|||
import { art } from '@/utils/render';
|
||||
import path from 'node:path';
|
||||
import { isValidHost } from '@/utils/valid-host';
|
||||
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
||||
|
||||
const shortcuts = {
|
||||
potd: 'picture/browse/potd/',
|
||||
|
|
@ -46,7 +47,7 @@ async function handler(ctx) {
|
|||
const language = ctx.req.param('language') ?? '';
|
||||
const category = ctx.req.param('category') ?? 'figure';
|
||||
if (language && !isValidHost(language)) {
|
||||
throw new Error('Invalid language');
|
||||
throw new InvalidParameterError('Invalid language');
|
||||
}
|
||||
|
||||
const rootUrl = `https://${language === 'en' || language === '' ? '' : `${language}.`}myfigurecollection.net`;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { Route } from '@/types';
|
|||
import got from '@/utils/got';
|
||||
import utils from './utils';
|
||||
import { config } from '@/config';
|
||||
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/douyin/:dyid',
|
||||
|
|
@ -31,7 +32,7 @@ export const route: Route = {
|
|||
|
||||
async function handler(ctx) {
|
||||
if (!config.newrank || !config.newrank.cookie) {
|
||||
throw new Error('newrank RSS is disabled due to the lack of <a href="https://docs.rsshub.app/deploy/config#route-specific-configurations">relevant config</a>');
|
||||
throw new ConfigNotFoundError('newrank RSS is disabled due to the lack of <a href="https://docs.rsshub.app/deploy/config#route-specific-configurations">relevant config</a>');
|
||||
}
|
||||
const uid = ctx.req.param('dyid');
|
||||
const nonce = utils.random_nonce(9);
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue