mirror of
https://github.com/DIYgod/RSSHub.git
synced 2026-08-30 16:55:08 +08:00
style(eslint): add eslint-unicorn (#14257)
* style: add eslint-unicorn * style: fix unicorn/no-useless-spread * style: fix unicorn/no-useless-promise-resolve-reject * style: fix unicorn/no-for-loop * fix: codeql bad HTML filtering regexp * fix: codeql incomplete replace * fix: unicorn/no-abusive-eslint-disable * style: fix unicorn/no-new-array * style: fix unicorn/no-typeof-undefined * style: fix unicorn/no-zero-fractions * style: fix unicorn/no-empty-file * style: fix unicorn/prefer-date-now * revert: auto fix unicorn/prefer-switch on lib/v2/kuaidi100/utils.js * style: fix unicorn/prefer-array-find * style: fix unicorn/prefer-array-flat * style: fix unicorn/prefer-array-flat-map * style: fix unicorn/prefer-at * style: fix unicorn/prefer-string-starts-ends-with * style: fix unicorn/prefer-includes * fix: codeql URL substring sanitization * style: fix unicorn/prefer-optional-catch-binding * style: fix unicorn/catch-error-name * style: fix unicorn/escape-case * style: fix unicorn/prefer-native-coercion-functions * style: fix unicorn/prefer-regexp-test * style: fix unicorn/require-array-join-separator * style: fix unicorn/prefer-math-trunc * style: fix unicorn/prefer-negative-index * style: fix unicorn/prefer-dom-node-dataset * style: fix unicorn/prefer-dom-node-text-content * style: fix unicorn/prefer-query-selector * style: fix unicorn/no-array-for-each * style: fix unicorn/no-negated-condition * style: fix unicorn/prefer-add-event-listener * style: fix unicorn/import-style * style: fix prefer-regex-literals * style: disable unicorn/no-useless-switch-case * style: disable unicorn/text-encoding-identifier-case * style: fix unicorn/prefer-set-has * style: fix unicorn/prefer-spread * revert: auto fix on lib/routes/universities/ynnu/edu/base64.js * style: fix unicorn/no-useless-undefined * style: fix unicorn/no-array-push-push * style: fix unicorn/no-useless-undefined again * style: fix unicorn/no-lonely-if * style: fix unicorn/prefer-reflect-apply * style: fix unicorn/switch-case-braces * style: fix unicorn/prefer-switch * style: fix unicorn/prefer-array-some * fix: deepscan UNUSED_VAR_ASSIGN * style: fix unicorn/prefer-ternary * fix: follow-up of unicorn/prefer-ternary * revert: auto fix of unicorn/prefer-string-slice for substring() * style: disable unicorn/prefer-string-slice fix: auto fix slice over deprecated substr * style: fix unicorn/throw-new-error * style: fix unicorn/filename-case * test: fix dateParser renaming * style: fix unicorn/better-regex * style: fix unicorn/prefer-string-replace-all * fix(deps): add sanitize-html * style: fix no-prototype-builtins * style: fix unicorn/consistent-destructuring * style: fix unicorn/consistent-function-scoping * style: fix unicorn/prefer-regexp-test * style: fix unicorn/prefer-logical-operator-over-ternary * style: fix unicorn/no-array-callback-reference * style: add prefer-object-has-own * style: warn unicorn/no-empty-file * style: fix unicorn/prefer-number-properties * style: fix no-useless-undefined again * style: fix unicorn/numeric-separators-style * style: disable unicorn/no-array-callback-reference false postive with cheerio
This commit is contained in:
+50
-42
@@ -1,24 +1,21 @@
|
||||
{
|
||||
"extends": ["eslint:recommended", "plugin:n/recommended", "plugin:prettier/recommended", "plugin:yml/recommended"],
|
||||
"plugins": ["prettier", "@stylistic/js"],
|
||||
"extends": ["eslint:recommended", "plugin:n/recommended", "plugin:unicorn/recommended", "plugin:prettier/recommended", "plugin:yml/recommended"],
|
||||
"plugins": ["prettier", "@stylistic/js", "unicorn"],
|
||||
"parserOptions": {
|
||||
"ecmaVersion": "latest",
|
||||
"sourceType": "module"
|
||||
},
|
||||
"env": {
|
||||
"node": true,
|
||||
"es6": true,
|
||||
"es2024": true,
|
||||
"browser": true
|
||||
},
|
||||
"rules": {
|
||||
// possible problems
|
||||
"array-callback-return": 2,
|
||||
"array-callback-return": ["error", { "allowImplicit": true }],
|
||||
"no-await-in-loop": 2,
|
||||
"no-control-regex": 0,
|
||||
"no-duplicate-imports": 2,
|
||||
"no-prototype-builtins": 0,
|
||||
"no-unsafe-negation": 2,
|
||||
"require-atomic-updates": 0,
|
||||
// suggestions
|
||||
"arrow-body-style": 2,
|
||||
"block-scoped-var": 2,
|
||||
@@ -29,16 +26,7 @@
|
||||
"no-eval": 2,
|
||||
"no-extend-native": 2,
|
||||
"no-extra-label": 2,
|
||||
"no-global-assign": 2,
|
||||
"no-implicit-coercion": [
|
||||
"error",
|
||||
{
|
||||
"boolean": false,
|
||||
"number": false,
|
||||
"string": false,
|
||||
"disallowTemplateShorthand": true
|
||||
}
|
||||
],
|
||||
"no-implicit-coercion": ["error", { "boolean": false, "number": false, "string": false, "disallowTemplateShorthand": true }],
|
||||
"no-implicit-globals": 2,
|
||||
"no-labels": 2,
|
||||
"no-multi-str": 2,
|
||||
@@ -52,9 +40,49 @@
|
||||
"object-shorthand": 2,
|
||||
"prefer-arrow-callback": 2,
|
||||
"prefer-const": 2,
|
||||
"prefer-regex-literals": 1,
|
||||
"prefer-object-has-own": 2,
|
||||
"prefer-regex-literals": ["error", { "disallowRedundantWrapping": true }],
|
||||
"require-await": 2,
|
||||
// plugin specific
|
||||
"unicorn/consistent-destructuring": 1,
|
||||
"unicorn/consistent-function-scoping": 1,
|
||||
"unicorn/explicit-length-check": 0,
|
||||
"unicorn/filename-case": ["error", { "case": "kebabCase", "ignore": [".*\\.(yaml|yml)$", "RequestInProgress\\.js$"] }],
|
||||
"unicorn/new-for-builtins": 0,
|
||||
"unicorn/no-array-callback-reference": 0,
|
||||
"unicorn/no-array-reduce": 1,
|
||||
"unicorn/no-await-expression-member": 1,
|
||||
"unicorn/no-empty-file": 1,
|
||||
"unicorn/no-hex-escape": 1,
|
||||
"unicorn/no-null": 0,
|
||||
"unicorn/no-object-as-default-parameter": 1,
|
||||
"unicorn/no-process-exit": 0,
|
||||
"unicorn/no-useless-switch-case": 0,
|
||||
"unicorn/no-useless-undefined": ["error", { "checkArguments": false }],
|
||||
"unicorn/numeric-separators-style": [
|
||||
"warn",
|
||||
{
|
||||
"onlyIfContainsSeparator": false,
|
||||
"number": { "minimumDigits": 7, "groupLength": 3 },
|
||||
"binary": { "minimumDigits": 9, "groupLength": 4 },
|
||||
"octal": { "minimumDigits": 9, "groupLength": 4 },
|
||||
"hexadecimal": { "minimumDigits": 5, "groupLength": 2 }
|
||||
}
|
||||
],
|
||||
"unicorn/prefer-code-point": 1,
|
||||
"unicorn/prefer-logical-operator-over-ternary": 1,
|
||||
"unicorn/prefer-module": 0,
|
||||
"unicorn/prefer-node-protocol": 0,
|
||||
"unicorn/prefer-number-properties": ["warn", { "checkInfinity": false }],
|
||||
"unicorn/prefer-object-from-entries": 1,
|
||||
"unicorn/prefer-regexp-test": 1,
|
||||
"unicorn/prefer-string-replace-all": 1,
|
||||
"unicorn/prefer-string-slice": 0,
|
||||
"unicorn/prefer-switch": ["error", { "emptyDefaultCase": "do-nothing-comment" }],
|
||||
"unicorn/prefer-top-level-await": 0,
|
||||
"unicorn/prevent-abbreviations": 0,
|
||||
"unicorn/switch-case-braces": ["error", "avoid"],
|
||||
"unicorn/text-encoding-identifier-case": 0,
|
||||
// previous eslint formatting rules
|
||||
"@stylistic/js/arrow-parens": 2,
|
||||
"@stylistic/js/arrow-spacing": 2,
|
||||
@@ -74,40 +102,20 @@
|
||||
"@stylistic/js/space-unary-ops": 2,
|
||||
"@stylistic/js/spaced-comment": 2,
|
||||
// https://github.com/eslint-community/eslint-plugin-n
|
||||
"n/no-extraneous-require": [
|
||||
"error",
|
||||
{
|
||||
"allowModules": ["puppeteer-extra-plugin-user-preferences", "puppeteer-extra-plugin-user-data-dir"]
|
||||
}
|
||||
],
|
||||
"n/no-extraneous-require": ["error", { "allowModules": ["puppeteer-extra-plugin-user-preferences", "puppeteer-extra-plugin-user-data-dir"] }],
|
||||
"n/no-deprecated-api": 1,
|
||||
"n/no-missing-require": 0,
|
||||
"n/no-process-exit": 0,
|
||||
"n/no-unpublished-require": [
|
||||
"error",
|
||||
{
|
||||
"allowModules": ["tosource"]
|
||||
}
|
||||
],
|
||||
"n/no-unpublished-require": ["error", { "allowModules": ["tosource"] }],
|
||||
"prettier/prettier": 0,
|
||||
"yml/quotes": [
|
||||
"error",
|
||||
{
|
||||
"prefer": "single"
|
||||
}
|
||||
]
|
||||
"yml/quotes": ["error", { "prefer": "single" }]
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.yaml", "*.yml"],
|
||||
"parser": "yaml-eslint-parser",
|
||||
"rules": {
|
||||
"lines-around-comment": [
|
||||
"error",
|
||||
{
|
||||
"beforeBlockComment": false
|
||||
}
|
||||
]
|
||||
"lines-around-comment": ["error", { "beforeBlockComment": false }]
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -167,7 +167,7 @@
|
||||
docs: 'https://docs.rsshub.app/routes/multimedia#onejav',
|
||||
source: '/',
|
||||
target: (params, url, document) => {
|
||||
const today = document.querySelector('div.card.mb-1.card-overview').getAttribute('data-date').replace(/-/g, '');
|
||||
const today = document.querySelector('div.card.mb-1.card-overview').dataset.date.replaceAll('-', '');
|
||||
return `/onejav/day/${today}`;
|
||||
},
|
||||
},
|
||||
@@ -215,7 +215,7 @@
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return `/sexinsex/${pid}/${typeid ? typeid : ''}`;
|
||||
return `/sexinsex/${pid}/${typeid ?? ''}`;
|
||||
},
|
||||
},
|
||||
],
|
||||
@@ -230,7 +230,7 @@
|
||||
target: (params, url) => {
|
||||
const id = new URL(url).searchParams.get('fid');
|
||||
const type = new URL(url).searchParams.get('type');
|
||||
return `/t66y/${id}/${type ? type : ''}`;
|
||||
return `/t66y/${id}/${type ?? ''}`;
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@@ -6,8 +6,7 @@ router.get('/routes/:name?', (ctx) => {
|
||||
let counter = 0;
|
||||
|
||||
const maintainer = require('./maintainer');
|
||||
Object.keys(maintainer).forEach((i) => {
|
||||
const path = i;
|
||||
for (const path of Object.keys(maintainer)) {
|
||||
const top = path.split('/')[1];
|
||||
|
||||
if (!ctx.params.name || top === ctx.params.name) {
|
||||
@@ -18,7 +17,7 @@ router.get('/routes/:name?', (ctx) => {
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ctx.body = { counter, result };
|
||||
});
|
||||
+5
-5
@@ -20,13 +20,13 @@ const antiHotlink = require('./middleware/anti-hotlink');
|
||||
const loadOnDemand = require('./middleware/load-on-demand');
|
||||
|
||||
const router = require('./router');
|
||||
const core_router = require('./core_router');
|
||||
const protected_router = require('./protected_router');
|
||||
const core_router = require('./core-router');
|
||||
const protected_router = require('./protected-router');
|
||||
const mount = require('koa-mount');
|
||||
|
||||
// API related
|
||||
const apiTemplate = require('./middleware/api-template');
|
||||
const api_router = require('./api_router');
|
||||
const api_router = require('./api-router');
|
||||
const apiResponseHandler = require('./middleware/api-response-handler');
|
||||
|
||||
process.on('uncaughtException', (e) => {
|
||||
@@ -37,8 +37,8 @@ const app = new Koa();
|
||||
app.proxy = true;
|
||||
|
||||
// favicon
|
||||
app.use(favicon(__dirname + '/favicon.png', { maxAge: 31536000000 }));
|
||||
app.use(serve(__dirname + '/static', { maxage: 31536000000 }));
|
||||
app.use(favicon(__dirname + '/favicon.png', { maxAge: 31_536_000_000 }));
|
||||
app.use(serve(__dirname + '/static', { maxage: 31_536_000_000 }));
|
||||
|
||||
// global error handing
|
||||
app.use(onerror);
|
||||
|
||||
+10
-10
@@ -45,21 +45,21 @@ const calculateValue = () => {
|
||||
socket: envs.SOCKET || null, // 监听 Unix Socket, null 为禁用
|
||||
},
|
||||
listenInaddrAny: envs.LISTEN_INADDR_ANY || 1, // 是否允许公网连接,取值 0 1
|
||||
requestRetry: parseInt(envs.REQUEST_RETRY) || 2, // 请求失败重试次数
|
||||
requestTimeout: parseInt(envs.REQUEST_TIMEOUT) || 30000, // Milliseconds to wait for the server to end the response before aborting the request
|
||||
ua: envs.UA ? envs.UA : envs.NO_RANDOM_UA === 'true' || envs.NO_RANDOM_UA === '1' ? TRUE_UA : randUserAgent({ browser: 'chrome', os: 'mac os', device: 'desktop' }),
|
||||
requestRetry: Number.parseInt(envs.REQUEST_RETRY) || 2, // 请求失败重试次数
|
||||
requestTimeout: Number.parseInt(envs.REQUEST_TIMEOUT) || 30000, // Milliseconds to wait for the server to end the response before aborting the request
|
||||
ua: envs.UA ?? (envs.NO_RANDOM_UA === 'true' || envs.NO_RANDOM_UA === '1' ? TRUE_UA : randUserAgent({ browser: 'chrome', os: 'mac os', device: 'desktop' })),
|
||||
trueUA: TRUE_UA,
|
||||
// cors request
|
||||
allowOrigin: envs.ALLOW_ORIGIN,
|
||||
// cache
|
||||
cache: {
|
||||
type: typeof envs.CACHE_TYPE === 'undefined' ? 'memory' : envs.CACHE_TYPE, // 缓存类型,支持 'memory' 和 'redis',设为空可以禁止缓存
|
||||
requestTimeout: parseInt(envs.CACHE_REQUEST_TIMEOUT) || 60,
|
||||
routeExpire: parseInt(envs.CACHE_EXPIRE) || 5 * 60, // 路由缓存时间,单位为秒
|
||||
contentExpire: parseInt(envs.CACHE_CONTENT_EXPIRE) || 1 * 60 * 60, // 不变内容缓存时间,单位为秒
|
||||
type: envs.CACHE_TYPE === undefined ? 'memory' : envs.CACHE_TYPE, // 缓存类型,支持 'memory' 和 'redis',设为空可以禁止缓存
|
||||
requestTimeout: Number.parseInt(envs.CACHE_REQUEST_TIMEOUT) || 60,
|
||||
routeExpire: Number.parseInt(envs.CACHE_EXPIRE) || 5 * 60, // 路由缓存时间,单位为秒
|
||||
contentExpire: Number.parseInt(envs.CACHE_CONTENT_EXPIRE) || 1 * 60 * 60, // 不变内容缓存时间,单位为秒
|
||||
},
|
||||
memory: {
|
||||
max: parseInt(envs.MEMORY_MAX) || Math.pow(2, 8), // The maximum number of items that remain in the cache. This must be a positive finite intger.
|
||||
max: Number.parseInt(envs.MEMORY_MAX) || Math.pow(2, 8), // The maximum number of items that remain in the cache. This must be a positive finite intger.
|
||||
// https://github.com/isaacs/node-lru-cache#options
|
||||
},
|
||||
redis: {
|
||||
@@ -96,7 +96,7 @@ const calculateValue = () => {
|
||||
showLoggerTimestamp: envs.SHOW_LOGGER_TIMESTAMP,
|
||||
sentry: {
|
||||
dsn: envs.SENTRY,
|
||||
routeTimeout: parseInt(envs.SENTRY_ROUTE_TIMEOUT) || 30000,
|
||||
routeTimeout: Number.parseInt(envs.SENTRY_ROUTE_TIMEOUT) || 30000,
|
||||
},
|
||||
// feed config
|
||||
hotlink: {
|
||||
@@ -110,7 +110,7 @@ const calculateValue = () => {
|
||||
allow_user_supply_unsafe_domain: envs.ALLOW_USER_SUPPLY_UNSAFE_DOMAIN === 'true',
|
||||
},
|
||||
suffix: envs.SUFFIX,
|
||||
titleLengthLimit: parseInt(envs.TITLE_LENGTH_LIMIT) || 150,
|
||||
titleLengthLimit: Number.parseInt(envs.TITLE_LENGTH_LIMIT) || 150,
|
||||
openai: {
|
||||
apiKey: envs.OPENAI_API_KEY,
|
||||
model: envs.OPENAI_MODEL || 'gpt-3.5-turbo-16k',
|
||||
|
||||
+2
-2
@@ -16,7 +16,7 @@ if (config.enableCluster && cluster.isMaster && process.env.NODE_ENV !== 'test'
|
||||
if (fs.existsSync(config.connect.socket)) {
|
||||
fs.unlinkSync(config.connect.socket);
|
||||
}
|
||||
server = app.listen(config.connect.socket, parseInt(config.listenInaddrAny) ? null : '127.0.0.1');
|
||||
server = app.listen(config.connect.socket, Number.parseInt(config.listenInaddrAny) ? null : '127.0.0.1');
|
||||
logger.info('Listening Unix Socket ' + config.connect.socket);
|
||||
process.on('SIGINT', () => {
|
||||
fs.unlinkSync(config.connect.socket);
|
||||
@@ -24,7 +24,7 @@ if (config.enableCluster && cluster.isMaster && process.env.NODE_ENV !== 'test'
|
||||
});
|
||||
}
|
||||
if (config.connect.port) {
|
||||
server = app.listen(config.connect.port, parseInt(config.listenInaddrAny) ? null : '127.0.0.1');
|
||||
server = app.listen(config.connect.port, Number.parseInt(config.listenInaddrAny) ? null : '127.0.0.1');
|
||||
logger.info('Listening Port ' + config.connect.port);
|
||||
}
|
||||
|
||||
|
||||
+9
-9
@@ -1,12 +1,12 @@
|
||||
const dirname = __dirname + '/v2';
|
||||
const fs = require('fs');
|
||||
const { join } = require('path');
|
||||
const path = require('path');
|
||||
|
||||
// Presence Check
|
||||
for (const dir of fs.readdirSync(dirname)) {
|
||||
const dirPath = join(dirname, dir);
|
||||
if (fs.existsSync(join(dirPath, 'router.js')) && !fs.existsSync(join(dirPath, 'maintainer.js'))) {
|
||||
throw Error(`No maintainer.js in "${dirPath}".`);
|
||||
const dirPath = path.join(dirname, dir);
|
||||
if (fs.existsSync(path.join(dirPath, 'router.js')) && !fs.existsSync(path.join(dirPath, 'maintainer.js'))) {
|
||||
throw new Error(`No maintainer.js in "${dirPath}".`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,15 +24,15 @@ for (const dir in maintainerPath) {
|
||||
|
||||
// typo check e.g., ✘ module.export, ✔ module.exports
|
||||
if (!Object.keys(routes).length) {
|
||||
throw Error(`No maintainer in "${dir}".`);
|
||||
throw new Error(`No maintainer in "${dir}".`);
|
||||
}
|
||||
for (const author of Object.values(routes)) {
|
||||
if (!Array.isArray(author)) {
|
||||
throw Error(`Maintainers' name should be an array in "${dir}".`);
|
||||
throw new TypeError(`Maintainers' name should be an array in "${dir}".`);
|
||||
}
|
||||
// check for [], [''] or ['Someone', '']
|
||||
if (author.length < 1 || author.includes('')) {
|
||||
throw Error(`Empty maintainer in "${dir}".`);
|
||||
throw new Error(`Empty maintainer in "${dir}".`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,11 +43,11 @@ for (const dir in maintainerPath) {
|
||||
|
||||
// 兼容旧版路由
|
||||
const router = require('./router');
|
||||
router.stack.forEach((e) => {
|
||||
for (const e of router.stack) {
|
||||
if (!maintainers[e.path]) {
|
||||
maintainers[e.path] = [];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = Object.keys(maintainers)
|
||||
.sort()
|
||||
|
||||
@@ -5,11 +5,11 @@ const isLocalhost = require('is-localhost-ip');
|
||||
const reject = (ctx) => {
|
||||
ctx.response.status = 403;
|
||||
|
||||
throw Error('Authentication failed. Access denied.');
|
||||
throw new Error('Authentication failed. Access denied.');
|
||||
};
|
||||
|
||||
const ipv4Pattern = /^(\d{1,3}\.){3}\d{1,3}$/;
|
||||
const cidrPattern = /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\/(\d{1,2})/;
|
||||
const cidrPattern = /((?:\d{1,3}\.){3}\d{1,3})\/(\d{1,2})/;
|
||||
|
||||
const ipInCidr = (cidr, ip) => {
|
||||
const cidrMatch = cidr.match(cidrPattern);
|
||||
@@ -17,7 +17,7 @@ const ipInCidr = (cidr, ip) => {
|
||||
if (!cidrMatch || !ipMatch) {
|
||||
return false;
|
||||
}
|
||||
const subnetMask = parseInt(cidrMatch[2]);
|
||||
const subnetMask = Number.parseInt(cidrMatch[2]);
|
||||
const cidrIpBits = ipv4ToBitsring(cidrMatch[1]).substring(0, subnetMask);
|
||||
const ipBits = ipv4ToBitsring(ip).substring(0, subnetMask);
|
||||
return cidrIpBits === ipBits;
|
||||
@@ -26,7 +26,7 @@ const ipInCidr = (cidr, ip) => {
|
||||
const ipv4ToBitsring = (ip) =>
|
||||
ip
|
||||
.split('.')
|
||||
.map((part) => ('00000000' + parseInt(part).toString(2)).slice(-8))
|
||||
.map((part) => ('00000000' + Number.parseInt(part).toString(2)).slice(-8))
|
||||
.join('');
|
||||
|
||||
module.exports = async (ctx, next) => {
|
||||
@@ -53,22 +53,16 @@ module.exports = async (ctx, next) => {
|
||||
return grant();
|
||||
}
|
||||
|
||||
if (config.accessKey) {
|
||||
if (config.accessKey === accessKey || accessCode === md5(requestPath + config.accessKey)) {
|
||||
return grant();
|
||||
}
|
||||
if (config.accessKey && (config.accessKey === accessKey || accessCode === md5(requestPath + config.accessKey))) {
|
||||
return grant();
|
||||
}
|
||||
|
||||
if (config.allowlist) {
|
||||
if (config.allowlist.find((item) => ip.includes(item) || ipInCidr(item, ip) || requestPath.includes(item) || requestUA.includes(item))) {
|
||||
return grant();
|
||||
}
|
||||
if (config.allowlist && config.allowlist.some((item) => ip.includes(item) || ipInCidr(item, ip) || requestPath.includes(item) || requestUA.includes(item))) {
|
||||
return grant();
|
||||
}
|
||||
|
||||
if (config.denylist) {
|
||||
if (!config.denylist.find((item) => ip.includes(item) || ipInCidr(item, ip) || requestPath.includes(item) || requestUA.includes(item))) {
|
||||
return grant();
|
||||
}
|
||||
if (config.denylist && !config.denylist.some((item) => ip.includes(item) || ipInCidr(item, ip) || requestPath.includes(item) || requestUA.includes(item))) {
|
||||
return grant();
|
||||
}
|
||||
|
||||
reject(ctx);
|
||||
|
||||
@@ -4,8 +4,8 @@ const logger = require('@/utils/logger');
|
||||
const path = require('path');
|
||||
const { art } = require('@/utils/render');
|
||||
|
||||
const templateRegex = /\$\{([^{}]+)}/g;
|
||||
const allowedUrlProperties = ['hash', 'host', 'hostname', 'href', 'origin', 'password', 'pathname', 'port', 'protocol', 'search', 'searchParams', 'username'];
|
||||
const templateRegex = /\${([^{}]+)}/g;
|
||||
const allowedUrlProperties = new Set(['hash', 'host', 'hostname', 'href', 'origin', 'password', 'pathname', 'port', 'protocol', 'search', 'searchParams', 'username']);
|
||||
const IframeWrapperTemplate = path.join(__dirname, 'templates/iframe.art');
|
||||
|
||||
// match path or sub-path
|
||||
@@ -26,7 +26,7 @@ const filterPath = (path) => {
|
||||
};
|
||||
|
||||
const interpolate = (str, obj) =>
|
||||
str.replace(templateRegex, (_, prop) => {
|
||||
str.replaceAll(templateRegex, (_, prop) => {
|
||||
let needEncode = false;
|
||||
if (prop.endsWith('_ue')) {
|
||||
// url encode
|
||||
@@ -39,7 +39,7 @@ const parseUrl = (str) => {
|
||||
let url;
|
||||
try {
|
||||
url = new URL(str);
|
||||
} catch (e) {
|
||||
} catch {
|
||||
logger.error(`Failed to parse ${str}`);
|
||||
}
|
||||
|
||||
@@ -87,12 +87,12 @@ const validateTemplate = (template) => {
|
||||
if (!template) {
|
||||
return;
|
||||
}
|
||||
[...template.matchAll(templateRegex)].forEach((match) => {
|
||||
for (const match of template.matchAll(templateRegex)) {
|
||||
const prop = match[1].endsWith('_ue') ? match[1].slice(0, -3) : match[1];
|
||||
if (!allowedUrlProperties.includes(prop)) {
|
||||
if (!allowedUrlProperties.has(prop)) {
|
||||
throw new Error(`Invalid URL property: ${prop}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = async (ctx, next) => {
|
||||
@@ -115,11 +115,7 @@ module.exports = async (ctx, next) => {
|
||||
|
||||
// Force config hotlink template on conflict
|
||||
if (config.hotlink.template) {
|
||||
if (!filterPath(ctx.request.path)) {
|
||||
image_hotlink_template = undefined;
|
||||
} else {
|
||||
image_hotlink_template = config.hotlink.template;
|
||||
}
|
||||
image_hotlink_template = filterPath(ctx.request.path) ? config.hotlink.template : undefined;
|
||||
}
|
||||
|
||||
if (!image_hotlink_template && !multimedia_hotlink_template && !shouldWrapInIframe) {
|
||||
@@ -138,11 +134,12 @@ module.exports = async (ctx, next) => {
|
||||
ctx.state.data.description = process(ctx.state.data.description, image_hotlink_template, multimedia_hotlink_template, shouldWrapInIframe);
|
||||
}
|
||||
|
||||
ctx.state.data.item &&
|
||||
ctx.state.data.item.forEach((item) => {
|
||||
if (ctx.state.data.item) {
|
||||
for (const item of ctx.state.data.item) {
|
||||
if (item.description) {
|
||||
item.description = process(item.description, image_hotlink_template, multimedia_hotlink_template, shouldWrapInIframe);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Vendored
+9
-9
@@ -57,22 +57,22 @@ module.exports = function (app) {
|
||||
...cacheModule,
|
||||
tryGet: async (key, getValueFunc, maxAge = config.cache.contentExpire, refresh = true) => {
|
||||
if (typeof key !== 'string') {
|
||||
throw Error('Cache key must be a string');
|
||||
throw new TypeError('Cache key must be a string');
|
||||
}
|
||||
let v = await get(key, refresh);
|
||||
if (!v) {
|
||||
v = await getValueFunc();
|
||||
set(key, v, maxAge);
|
||||
} else {
|
||||
if (v) {
|
||||
let parsed;
|
||||
try {
|
||||
parsed = JSON.parse(v);
|
||||
} catch (e) {
|
||||
} catch {
|
||||
parsed = null;
|
||||
}
|
||||
if (parsed) {
|
||||
v = parsed;
|
||||
}
|
||||
} else {
|
||||
v = await getValueFunc();
|
||||
set(key, v, maxAge);
|
||||
}
|
||||
|
||||
return v;
|
||||
@@ -112,7 +112,7 @@ module.exports = function (app) {
|
||||
ctx.state.data = JSON.parse(value);
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
} catch {
|
||||
//
|
||||
}
|
||||
|
||||
@@ -121,9 +121,9 @@ module.exports = function (app) {
|
||||
|
||||
try {
|
||||
await next();
|
||||
} catch (e) {
|
||||
} catch (error) {
|
||||
await globalCache.set(controlKey, '0', config.cache.requestTimeout);
|
||||
throw e;
|
||||
throw error;
|
||||
}
|
||||
|
||||
if (ctx.response.get('Cache-Control') !== 'no-cache' && ctx.state && ctx.state.data) {
|
||||
|
||||
Vendored
+4
-4
@@ -20,7 +20,7 @@ redisClient.on('connect', () => {
|
||||
|
||||
const getCacheTtlKey = (key) => {
|
||||
if (key.startsWith('rsshub:cacheTtl:')) {
|
||||
throw Error('"rsshub:cacheTtl:" prefix is reserved for the internal usage, please change your cache key'); // blocking any attempt to get/set the cacheTtl
|
||||
throw new Error('"rsshub:cacheTtl:" prefix is reserved for the internal usage, please change your cache key'); // blocking any attempt to get/set the cacheTtl
|
||||
}
|
||||
return `rsshub:cacheTtl:${key}`;
|
||||
};
|
||||
@@ -31,13 +31,13 @@ module.exports = {
|
||||
const cacheTtlKey = getCacheTtlKey(key);
|
||||
let [value, cacheTtl] = await redisClient.mget(key, cacheTtlKey);
|
||||
if (value && refresh) {
|
||||
if (!cacheTtl) {
|
||||
if (cacheTtl) {
|
||||
redisClient.expire(cacheTtlKey, cacheTtl);
|
||||
} else {
|
||||
// if cacheTtl is not set, that means the cache expire time is contentExpire
|
||||
cacheTtl = config.cache.contentExpire;
|
||||
// dont save cacheTtl to Redis, as it is the default value
|
||||
// redisClient.set(cacheTtlKey, cacheTtl, 'EX', cacheTtl);
|
||||
} else {
|
||||
redisClient.expire(cacheTtlKey, cacheTtl);
|
||||
}
|
||||
redisClient.expire(key, cacheTtl);
|
||||
value = value + '';
|
||||
|
||||
@@ -24,7 +24,7 @@ module.exports = async (ctx, next) => {
|
||||
return;
|
||||
}
|
||||
|
||||
const status = (ctx.status / 100) | 0;
|
||||
const status = Math.trunc(ctx.status / 100);
|
||||
if (2 !== status) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,9 @@ module.exports = function (app) {
|
||||
|
||||
if (p.length > 0) {
|
||||
modName = p[0];
|
||||
if (!loadedRoutes.has(modName)) {
|
||||
if (loadedRoutes.has(modName)) {
|
||||
mounted = true;
|
||||
} else {
|
||||
const mod = routes[modName];
|
||||
// Mount module
|
||||
if (mod) {
|
||||
@@ -21,8 +23,6 @@ module.exports = function (app) {
|
||||
mod(router);
|
||||
app.use(mount(`/${modName}`, router.routes())).use(router.allowedMethods());
|
||||
}
|
||||
} else {
|
||||
mounted = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+15
-15
@@ -20,15 +20,15 @@ if (config.sentry.dsn) {
|
||||
|
||||
try {
|
||||
gitHash = require('git-rev-sync').short();
|
||||
} catch (e) {
|
||||
} catch {
|
||||
gitHash = (process.env.HEROKU_SLUG_COMMIT && process.env.HEROKU_SLUG_COMMIT.slice(0, 7)) || (process.env.VERCEL_GIT_COMMIT_SHA && process.env.VERCEL_GIT_COMMIT_SHA.slice(0, 7)) || 'unknown';
|
||||
}
|
||||
|
||||
module.exports = async (ctx, next) => {
|
||||
try {
|
||||
const time = +new Date();
|
||||
const time = Date.now();
|
||||
await next();
|
||||
if (config.sentry.dsn && +new Date() - time >= config.sentry.routeTimeout) {
|
||||
if (config.sentry.dsn && Date.now() - time >= config.sentry.routeTimeout) {
|
||||
Sentry.withScope((scope) => {
|
||||
scope.setTag('route', ctx._matchedRoute);
|
||||
scope.setTag('name', ctx.request.path.split('/')[1]);
|
||||
@@ -36,8 +36,8 @@ module.exports = async (ctx, next) => {
|
||||
Sentry.captureException(new Error('Route Timeout'));
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
if (err instanceof Error && !err.stack.split('\n')[1].includes('lib/middleware/parameter.js')) {
|
||||
} catch (error) {
|
||||
if (error instanceof Error && !error.stack.split('\n')[1].includes('lib/middleware/parameter.js')) {
|
||||
// Append v2 route path if a route throws an error
|
||||
// since koa-mount will remove the mount path from ctx.request.path
|
||||
// https://github.com/koajs/mount/issues/62
|
||||
@@ -45,11 +45,11 @@ module.exports = async (ctx, next) => {
|
||||
ctx._matchedRoute = ctx._matchedRoute ? (ctx.mountPath ?? '') + ctx._matchedRoute : ctx._matchedRoute;
|
||||
}
|
||||
|
||||
let message = err;
|
||||
if (err.name && (err.name === 'HTTPError' || err.name === 'RequestError')) {
|
||||
message = `${err.message}: target website might be blocking our access, you can <a href="https://docs.rsshub.app/install/">host your own RSSHub instance</a> for a better usability.`;
|
||||
} else if (err instanceof Error) {
|
||||
message = process.env.NODE_ENV === 'production' ? err.message : err.stack;
|
||||
let message = error;
|
||||
if (error.name && (error.name === 'HTTPError' || error.name === 'RequestError')) {
|
||||
message = `${error.message}: target website might be blocking our access, you can <a href="https://docs.rsshub.app/install/">host your own RSSHub instance</a> for a better usability.`;
|
||||
} else if (error instanceof Error) {
|
||||
message = process.env.NODE_ENV === 'production' ? error.message : error.stack;
|
||||
}
|
||||
|
||||
logger.error(`Error in ${ctx.request.path}: ${message}`);
|
||||
@@ -57,7 +57,7 @@ module.exports = async (ctx, next) => {
|
||||
if (config.isPackage) {
|
||||
ctx.body = {
|
||||
error: {
|
||||
message: err.message ? err.message : err,
|
||||
message: error.message ?? error,
|
||||
},
|
||||
};
|
||||
} else {
|
||||
@@ -65,12 +65,12 @@ module.exports = async (ctx, next) => {
|
||||
'Content-Type': 'text/html; charset=UTF-8',
|
||||
});
|
||||
|
||||
if (err instanceof RequestInProgressError) {
|
||||
if (error instanceof RequestInProgressError) {
|
||||
ctx.status = 503;
|
||||
message = err.message;
|
||||
message = error.message;
|
||||
ctx.set('Cache-Control', `public, max-age=${config.cache.requestTimeout}`);
|
||||
} else if (ctx.status === 403) {
|
||||
message = err.message;
|
||||
message = error.message;
|
||||
} else {
|
||||
ctx.status = 404;
|
||||
}
|
||||
@@ -112,7 +112,7 @@ module.exports = async (ctx, next) => {
|
||||
scope.setTag('route', ctx._matchedRoute);
|
||||
scope.setTag('name', ctx.request.path.split('/')[1]);
|
||||
scope.addEventProcessor((event) => Sentry.Handlers.parseRequest(event, ctx.request));
|
||||
Sentry.captureException(err);
|
||||
Sentry.captureException(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+24
-36
@@ -21,7 +21,7 @@ const resolveRelativeLink = ($, elem, attr, baseUrl) => {
|
||||
// e.g. <video><source src="https://example.com"></video> should leave <video> unchanged
|
||||
$elem.attr(attr, new URL(oldAttr, baseUrl).href);
|
||||
}
|
||||
} catch (e) {
|
||||
} catch {
|
||||
// no-empty
|
||||
}
|
||||
}
|
||||
@@ -51,12 +51,12 @@ module.exports = async (ctx, next) => {
|
||||
await next();
|
||||
|
||||
if (!ctx.state.data && !ctx._matchedRoute) {
|
||||
throw Error('wrong path');
|
||||
throw new Error('wrong path');
|
||||
}
|
||||
|
||||
if (ctx.state.data) {
|
||||
if ((!ctx.state.data.item || ctx.state.data.item.length === 0) && !ctx.state.data.allowEmpty) {
|
||||
throw Error('this route is empty, please check the original site or <a href="https://github.com/DIYgod/RSSHub/issues/new/choose">create an issue</a>');
|
||||
throw new Error('this route is empty, please check the original site or <a href="https://github.com/DIYgod/RSSHub/issues/new/choose">create an issue</a>');
|
||||
}
|
||||
|
||||
// fix allowEmpty
|
||||
@@ -82,12 +82,8 @@ module.exports = async (ctx, next) => {
|
||||
// handle link
|
||||
if (item.link) {
|
||||
let baseUrl = ctx.state.data.link;
|
||||
if (baseUrl && !baseUrl.match(/^https?:\/\//)) {
|
||||
if (baseUrl.match(/^\/\//)) {
|
||||
baseUrl = 'http:' + baseUrl;
|
||||
} else {
|
||||
baseUrl = 'http://' + baseUrl;
|
||||
}
|
||||
if (baseUrl && !/^https?:\/\//.test(baseUrl)) {
|
||||
baseUrl = /^\/\//.test(baseUrl) ? 'http:' + baseUrl : 'http://' + baseUrl;
|
||||
}
|
||||
|
||||
item.link = new URL(item.link, baseUrl).href;
|
||||
@@ -98,12 +94,8 @@ module.exports = async (ctx, next) => {
|
||||
const $ = cheerio.load(item.description);
|
||||
let baseUrl = item.link || ctx.state.data.link;
|
||||
|
||||
if (baseUrl && !baseUrl.match(/^https?:\/\//)) {
|
||||
if (baseUrl.match(/^\/\//)) {
|
||||
baseUrl = 'http:' + baseUrl;
|
||||
} else {
|
||||
baseUrl = 'http://' + baseUrl;
|
||||
}
|
||||
if (baseUrl && !/^https?:\/\//.test(baseUrl)) {
|
||||
baseUrl = /^\/\//.test(baseUrl) ? 'http:' + baseUrl : 'http://' + baseUrl;
|
||||
}
|
||||
|
||||
$('script').remove();
|
||||
@@ -128,9 +120,9 @@ module.exports = async (ctx, next) => {
|
||||
}
|
||||
|
||||
// redundant attributes
|
||||
['onclick', 'onerror', 'onload'].forEach((e) => {
|
||||
for (const e of ['onclick', 'onerror', 'onload']) {
|
||||
$ele.removeAttr(e);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// resolve relative link & fix referrer policy
|
||||
@@ -170,7 +162,7 @@ module.exports = async (ctx, next) => {
|
||||
return item;
|
||||
};
|
||||
|
||||
ctx.state.data.item = await Promise.all(ctx.state.data.item.map(handleItem));
|
||||
ctx.state.data.item = await Promise.all(ctx.state.data.item.map((itm) => handleItem(itm)));
|
||||
|
||||
if (ctx.query) {
|
||||
// filter
|
||||
@@ -187,7 +179,7 @@ module.exports = async (ctx, next) => {
|
||||
case 're2':
|
||||
return RE2JS.compile(string, insensitive ? RE2JS.CASE_INSENSITIVE : 0);
|
||||
default:
|
||||
throw Error(`Invalid Engine Value: ${engine}, please check your config.`);
|
||||
throw new Error(`Invalid Engine Value: ${engine}, please check your config.`);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -262,8 +254,8 @@ module.exports = async (ctx, next) => {
|
||||
ctx.state.data.item = ctx.state.data.item.filter(({ pubDate }) => {
|
||||
let isFilter = true;
|
||||
try {
|
||||
isFilter = !pubDate || now - new Date(pubDate).getTime() <= parseInt(ctx.query.filter_time) * 1000;
|
||||
} catch (err) {
|
||||
isFilter = !pubDate || now - new Date(pubDate).getTime() <= Number.parseInt(ctx.query.filter_time) * 1000;
|
||||
} catch {
|
||||
// no-empty
|
||||
}
|
||||
return isFilter;
|
||||
@@ -272,7 +264,7 @@ module.exports = async (ctx, next) => {
|
||||
|
||||
// limit
|
||||
if (ctx.query.limit) {
|
||||
ctx.state.data.item = ctx.state.data.item.slice(0, parseInt(ctx.query.limit));
|
||||
ctx.state.data.item = ctx.state.data.item.slice(0, Number.parseInt(ctx.query.limit));
|
||||
}
|
||||
|
||||
// telegram instant view
|
||||
@@ -299,7 +291,7 @@ module.exports = async (ctx, next) => {
|
||||
html: $.html(),
|
||||
});
|
||||
return result;
|
||||
} catch (e) {
|
||||
} catch {
|
||||
// no-empty
|
||||
}
|
||||
});
|
||||
@@ -328,7 +320,7 @@ module.exports = async (ctx, next) => {
|
||||
if (summary !== '') {
|
||||
item.description = summary + '<hr/><br/>' + item.description;
|
||||
}
|
||||
} catch (e) {
|
||||
} catch {
|
||||
// when openai failed, return default description and not write cache
|
||||
}
|
||||
}
|
||||
@@ -347,32 +339,28 @@ module.exports = async (ctx, next) => {
|
||||
|
||||
// opencc
|
||||
if (ctx.query.opencc) {
|
||||
ctx.state.data.item.forEach((item) => {
|
||||
for (const item of ctx.state.data.item) {
|
||||
item.title = simplecc(item.title ?? item.link, ctx.query.opencc);
|
||||
item.description = simplecc(item.description ?? item.title ?? item.link, ctx.query.opencc);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// brief
|
||||
if (ctx.query.brief) {
|
||||
const num = /[1-9]\d{2,}/;
|
||||
if (num.test(ctx.query.brief)) {
|
||||
ctx.query.brief = parseInt(ctx.query.brief);
|
||||
ctx.state.data.item.forEach((item) => {
|
||||
ctx.query.brief = Number.parseInt(ctx.query.brief);
|
||||
for (const item of ctx.state.data.item) {
|
||||
let text;
|
||||
if (item.description) {
|
||||
text = item.description.replace(/<\/?[^>]+(>|$)/g, '');
|
||||
text = item.description.replaceAll(/<\/?[^>]+(>|$)/g, '');
|
||||
}
|
||||
if (text?.length) {
|
||||
if (text.length > ctx.query.brief) {
|
||||
item.description = `<p>${text.substring(0, ctx.query.brief)}…</p>`;
|
||||
} else {
|
||||
item.description = `<p>${text}</p>`;
|
||||
}
|
||||
item.description = text.length > ctx.query.brief ? `<p>${text.substring(0, ctx.query.brief)}…</p>` : `<p>${text}</p>`;
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
throw Error(`Invalid parameter brief. Please check the doc https://docs.rsshub.app/parameter#shu-chu-jian-xun`);
|
||||
throw new Error(`Invalid parameter brief. Please check the doc https://docs.rsshub.app/parameter#shu-chu-jian-xun`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+38
-42
@@ -22,11 +22,7 @@ module.exports = async (ctx, next) => {
|
||||
ctx.set({
|
||||
'Content-Type': 'application/json; charset=UTF-8',
|
||||
});
|
||||
if (ctx.state.json) {
|
||||
ctx.body = JSON.stringify(ctx.state.json, null, 4);
|
||||
} else {
|
||||
ctx.body = JSON.stringify({ message: 'plugin does not set debug json' });
|
||||
}
|
||||
ctx.body = ctx.state.json ? JSON.stringify(ctx.state.json, null, 4) : JSON.stringify({ message: 'plugin does not set debug json' });
|
||||
}
|
||||
|
||||
if (outputType.endsWith('.debug.html')) {
|
||||
@@ -34,12 +30,8 @@ module.exports = async (ctx, next) => {
|
||||
'Content-Type': 'text/html; charset=UTF-8',
|
||||
});
|
||||
|
||||
const index = parseInt(outputType.match(/(\d+)\.debug\.html$/)[1]);
|
||||
if (!(ctx.state.data && ctx.state.data.item && ctx.state.data.item[index])) {
|
||||
ctx.body = `ctx.state.data.item[${index}] not found`;
|
||||
} else {
|
||||
ctx.body = ctx.state.data.item[index].description;
|
||||
}
|
||||
const index = Number.parseInt(outputType.match(/(\d+)\.debug\.html$/)[1]);
|
||||
ctx.body = ctx.state.data && ctx.state.data.item && ctx.state.data.item[index] ? ctx.state.data.item[index].description : `ctx.state.data.item[${index}] not found`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,55 +41,59 @@ module.exports = async (ctx, next) => {
|
||||
|
||||
if (ctx.state.data) {
|
||||
const collapseWhitespaceForProperties = (properties, obj) => {
|
||||
properties.forEach((prop) => {
|
||||
for (const prop of properties) {
|
||||
if (obj[prop]) {
|
||||
obj[prop] = collapseWhitespace(obj[prop]);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
collapseWhitespaceForProperties(['title', 'subtitle', 'author'], ctx.state.data);
|
||||
|
||||
ctx.state.data.item?.forEach((item) => {
|
||||
if (item.title) {
|
||||
item.title = collapseWhitespace(item.title);
|
||||
// trim title length
|
||||
for (let length = 0, i = 0; i < item.title.length; i++) {
|
||||
length += Buffer.from(item.title[i]).length !== 1 ? 2 : 1;
|
||||
if (length > config.titleLengthLimit) {
|
||||
item.title = `${item.title.slice(0, i)}...`;
|
||||
break;
|
||||
if (ctx.state.data.item) {
|
||||
for (const item of ctx.state.data.item) {
|
||||
if (item.title) {
|
||||
item.title = collapseWhitespace(item.title);
|
||||
// trim title length
|
||||
for (let length = 0, i = 0; i < item.title.length; i++) {
|
||||
length += Buffer.from(item.title[i]).length === 1 ? 1 : 2;
|
||||
if (length > config.titleLengthLimit) {
|
||||
item.title = `${item.title.slice(0, i)}...`;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof item.author === 'string') {
|
||||
item.author = collapseWhitespace(item.author);
|
||||
} else if (typeof item.author === 'object' && item.author !== null) {
|
||||
item.author.forEach((a) => (a.name = collapseWhitespace(a.name)));
|
||||
if (outputType !== 'json') {
|
||||
item.author = item.author.map((a) => a.name).join(', ');
|
||||
if (typeof item.author === 'string') {
|
||||
item.author = collapseWhitespace(item.author);
|
||||
} else if (typeof item.author === 'object' && item.author !== null) {
|
||||
for (const a of item.author) {
|
||||
a.name = collapseWhitespace(a.name);
|
||||
}
|
||||
if (outputType !== 'json') {
|
||||
item.author = item.author.map((a) => a.name).join(', ');
|
||||
}
|
||||
}
|
||||
|
||||
if (item.itunes_duration && ((typeof item.itunes_duration === 'string' && !item.itunes_duration.includes(':')) || (typeof item.itunes_duration === 'number' && !isNaN(item.itunes_duration)))) {
|
||||
item.itunes_duration = +item.itunes_duration;
|
||||
item.itunes_duration =
|
||||
Math.floor(item.itunes_duration / 3600) + ':' + (Math.floor((item.itunes_duration % 3600) / 60) / 100).toFixed(2).slice(-2) + ':' + (((item.itunes_duration % 3600) % 60) / 100).toFixed(2).slice(-2);
|
||||
}
|
||||
|
||||
if (outputType !== 'rss') {
|
||||
item.pubDate = convertDateToISO8601(item.pubDate);
|
||||
item.updated = convertDateToISO8601(item.updated);
|
||||
}
|
||||
}
|
||||
|
||||
if (item.itunes_duration && ((typeof item.itunes_duration === 'string' && item.itunes_duration.indexOf(':') === -1) || (typeof item.itunes_duration === 'number' && !isNaN(item.itunes_duration)))) {
|
||||
item.itunes_duration = +item.itunes_duration;
|
||||
item.itunes_duration =
|
||||
Math.floor(item.itunes_duration / 3600) + ':' + (Math.floor((item.itunes_duration % 3600) / 60) / 100).toFixed(2).slice(-2) + ':' + (((item.itunes_duration % 3600) % 60) / 100).toFixed(2).slice(-2);
|
||||
}
|
||||
|
||||
if (outputType !== 'rss') {
|
||||
item.pubDate = convertDateToISO8601(item.pubDate);
|
||||
item.updated = convertDateToISO8601(item.updated);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const currentDate = new Date();
|
||||
const data = {
|
||||
lastBuildDate: currentDate.toUTCString(),
|
||||
updated: currentDate.toISOString(),
|
||||
ttl: (config.cache.routeExpire / 60) | 0,
|
||||
ttl: Math.trunc(config.cache.routeExpire / 60),
|
||||
atomlink: ctx.request.href,
|
||||
...ctx.state.data,
|
||||
};
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
// https://stackoverflow.com/questions/1497885/remove-control-characters-from-php-string/1497928#1497928
|
||||
module.exports = async (ctx, next) => {
|
||||
await next();
|
||||
ctx.body = typeof ctx.body !== 'object' ? ctx.body.replace(/[\x00-\x09\x0B\x0C\x0E-\x1F\x7F]/g, '') : ctx.body;
|
||||
ctx.body = typeof ctx.body === 'object' ? ctx.body : ctx.body.replaceAll(/[\u0000-\u0009\u000B\u000C\u000E-\u001F\u007F]/g, '');
|
||||
};
|
||||
|
||||
+3
-3
@@ -461,7 +461,7 @@ module.exports = {
|
||||
docs: 'https://docs.rsshub.app/routes/multimedia#onejav',
|
||||
source: '/',
|
||||
target: (params, url, document) => {
|
||||
const today = document.querySelector('div.card.mb-1.card-overview').getAttribute('data-date').replace(/-/g, '');
|
||||
const today = document.querySelector('div.card.mb-1.card-overview').dataset.date.replaceAll('-', '');
|
||||
return `/onejav/day/${today}`;
|
||||
},
|
||||
},
|
||||
@@ -509,7 +509,7 @@ module.exports = {
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return `/sexinsex/${pid}/${typeid ? typeid : ''}`;
|
||||
return `/sexinsex/${pid}/${typeid ?? ''}`;
|
||||
},
|
||||
},
|
||||
],
|
||||
@@ -524,7 +524,7 @@ module.exports = {
|
||||
target: (params, url) => {
|
||||
const id = new URL(url).searchParams.get('fid');
|
||||
const type = new URL(url).searchParams.get('type');
|
||||
return `/t66y/${id}/${type ? type : ''}`;
|
||||
return `/t66y/${id}/${type ?? ''}`;
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
+23
-23
@@ -1,75 +1,75 @@
|
||||
const dirname = __dirname + '/v2';
|
||||
const fs = require('fs');
|
||||
const toSource = require('tosource');
|
||||
const { join } = require('path');
|
||||
const path = require('path');
|
||||
|
||||
// Namespaces that do not require radar.js
|
||||
const allowNamespace = ['discourse', 'discuz', 'ehentai', 'lemmy', 'mail', 'test'];
|
||||
const allowNamespace = new Set(['discourse', 'discuz', 'ehentai', 'lemmy', 'mail', 'test']);
|
||||
// Check if a radar.js file is exist under each folder of dirname
|
||||
for (const dir of fs.readdirSync(dirname)) {
|
||||
const dirPath = join(dirname, dir);
|
||||
if (!fs.existsSync(join(dirPath, 'radar.js')) && !allowNamespace.includes(dir)) {
|
||||
throw Error(`No radar.js in "${dirPath}".`);
|
||||
const dirPath = path.join(dirname, dir);
|
||||
if (!fs.existsSync(path.join(dirPath, 'radar.js')) && !allowNamespace.has(dir)) {
|
||||
throw new Error(`No radar.js in "${dirPath}".`);
|
||||
}
|
||||
}
|
||||
|
||||
const validateRadarRules = (rule, dir) => {
|
||||
const allowDomains = ['www.gov.cn'];
|
||||
const allowDomains = new Set(['www.gov.cn']);
|
||||
const blockWords = ['/', 'http', 'www'];
|
||||
const domain = Object.keys(rule);
|
||||
if (!domain.length && !allowNamespace.includes(dir)) {
|
||||
if (!domain.length && !allowNamespace.has(dir)) {
|
||||
// typo check e.g., ✘ module.export, ✔ module.exports
|
||||
throw Error(`No Radar rule in "${dir}".`);
|
||||
throw new Error(`No Radar rule in "${dir}".`);
|
||||
}
|
||||
for (const [d, r] of Object.entries(rule)) {
|
||||
if (blockWords.some((word) => d.startsWith(word)) && !allowDomains.includes(d)) {
|
||||
throw Error(`Domain name "${d}" should not contain any of ${blockWords.join(', ')}.`);
|
||||
if (blockWords.some((word) => d.startsWith(word)) && !allowDomains.has(d)) {
|
||||
throw new Error(`Domain name "${d}" should not contain any of ${blockWords.join(', ')}.`);
|
||||
}
|
||||
if (!r.hasOwnProperty('_name')) {
|
||||
throw Error(`No _name in "${dir}".`);
|
||||
if (!Object.hasOwn(r, '_name')) {
|
||||
throw new Error(`No _name in "${dir}".`);
|
||||
}
|
||||
// property check
|
||||
for (const [host, items] of Object.entries(r)) {
|
||||
if (host !== '_name') {
|
||||
if (!Array.isArray(items)) {
|
||||
throw Error(`Radar rules for domain "${host}" in "${dir}" should be placed in an array.`);
|
||||
throw new TypeError(`Radar rules for domain "${host}" in "${dir}" should be placed in an array.`);
|
||||
}
|
||||
for (const item of items) {
|
||||
if (!item.hasOwnProperty('title') || !item.hasOwnProperty('docs')) {
|
||||
throw Error(`Radar rules for "${host}" in "${dir}" should have at least "title" and "docs".`);
|
||||
if (!Object.hasOwn(item, 'title') || !Object.hasOwn(item, 'docs')) {
|
||||
throw new Error(`Radar rules for "${host}" in "${dir}" should have at least "title" and "docs".`);
|
||||
}
|
||||
if (!item.title || !item.docs) {
|
||||
throw Error(`Radar rules for "${host}" in "${dir}" should not be empty.`);
|
||||
throw new Error(`Radar rules for "${host}" in "${dir}" should not be empty.`);
|
||||
}
|
||||
if (!item.docs.startsWith('https://docs.rsshub.app/')) {
|
||||
throw Error(`Radar rules for "${host}" in "${dir}" should start with 'https://docs.rsshub.app/'.`);
|
||||
throw new Error(`Radar rules for "${host}" in "${dir}" should start with 'https://docs.rsshub.app/'.`);
|
||||
}
|
||||
if (Array.isArray(item.source)) {
|
||||
if (!item.source.length) {
|
||||
// check for []
|
||||
throw Error(`Radar rule of "${item.title}" for subdomain "${host}" in "${dir}" should not be empty.`);
|
||||
throw new Error(`Radar rule of "${item.title}" for subdomain "${host}" in "${dir}" should not be empty.`);
|
||||
}
|
||||
if (item.source.some((s) => s.includes('#') || s.includes('='))) {
|
||||
// Some will try to match '/some/path?a=1' which is not supported
|
||||
throw Error(`Radar rule of "${item.title}" for subdomain "${host}" in "${dir}" cannot match URL hash or URL search parameters.`);
|
||||
throw new Error(`Radar rule of "${item.title}" for subdomain "${host}" in "${dir}" cannot match URL hash or URL search parameters.`);
|
||||
}
|
||||
if (item.source.some((s) => !s.length)) {
|
||||
// check for ['/some/thing', ''] and ['']
|
||||
throw Error(`Radar rule of "${item.title}" for subdomain "${host}" in "${dir}" should not be empty.`);
|
||||
throw new Error(`Radar rule of "${item.title}" for subdomain "${host}" in "${dir}" should not be empty.`);
|
||||
}
|
||||
}
|
||||
if (typeof item.source === 'string') {
|
||||
if (!item.source.length) {
|
||||
// check for ''
|
||||
throw Error(`Radar rule of "${item.title}" for subdomain "${host}" in "${dir}" should not be empty.`);
|
||||
throw new Error(`Radar rule of "${item.title}" for subdomain "${host}" in "${dir}" should not be empty.`);
|
||||
}
|
||||
if (item.source.includes('#') || item.source.includes('=')) {
|
||||
throw Error(`Radar rule of "${item.title}" for subdomain "${host}" in "${dir}" cannot match URL hash or URL search parameters.`);
|
||||
throw new Error(`Radar rule of "${item.title}" for subdomain "${host}" in "${dir}" cannot match URL hash or URL search parameters.`);
|
||||
}
|
||||
}
|
||||
for (const key in item) {
|
||||
if (key !== 'title' && key !== 'docs' && key !== 'source' && key !== 'target') {
|
||||
throw Error(`Radar rules for "${host}" in "${dir}" should not have property "${key}".`);
|
||||
throw new Error(`Radar rules for "${host}" in "${dir}" should not have property "${key}".`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+31
-31
@@ -53,12 +53,12 @@ router.get('/huya/live/:id', lazyloadRouteHandler('./routes/huya/live'));
|
||||
router.get('/fdroid/apprelease/:app', lazyloadRouteHandler('./routes/fdroid/apprelease'));
|
||||
|
||||
// konachan
|
||||
router.get('/konachan/post/popular_recent', lazyloadRouteHandler('./routes/konachan/post_popular_recent'));
|
||||
router.get('/konachan.com/post/popular_recent', lazyloadRouteHandler('./routes/konachan/post_popular_recent'));
|
||||
router.get('/konachan.net/post/popular_recent', lazyloadRouteHandler('./routes/konachan/post_popular_recent'));
|
||||
router.get('/konachan/post/popular_recent/:period', lazyloadRouteHandler('./routes/konachan/post_popular_recent'));
|
||||
router.get('/konachan.com/post/popular_recent/:period', lazyloadRouteHandler('./routes/konachan/post_popular_recent'));
|
||||
router.get('/konachan.net/post/popular_recent/:period', lazyloadRouteHandler('./routes/konachan/post_popular_recent'));
|
||||
router.get('/konachan/post/popular_recent', lazyloadRouteHandler('./routes/konachan/post-popular-recent'));
|
||||
router.get('/konachan.com/post/popular_recent', lazyloadRouteHandler('./routes/konachan/post-popular-recent'));
|
||||
router.get('/konachan.net/post/popular_recent', lazyloadRouteHandler('./routes/konachan/post-popular-recent'));
|
||||
router.get('/konachan/post/popular_recent/:period', lazyloadRouteHandler('./routes/konachan/post-popular-recent'));
|
||||
router.get('/konachan.com/post/popular_recent/:period', lazyloadRouteHandler('./routes/konachan/post-popular-recent'));
|
||||
router.get('/konachan.net/post/popular_recent/:period', lazyloadRouteHandler('./routes/konachan/post-popular-recent'));
|
||||
|
||||
// PornHub
|
||||
// router.get('/pornhub/category/:caty', lazyloadRouteHandler('./routes/pornhub/category'));
|
||||
@@ -69,8 +69,8 @@ router.get('/konachan.net/post/popular_recent/:period', lazyloadRouteHandler('./
|
||||
// router.get('/pornhub/:language?/pornstar/:username/:sort?', lazyloadRouteHandler('./routes/pornhub/pornstar'));
|
||||
|
||||
// yande.re
|
||||
router.get('/yande.re/post/popular_recent', lazyloadRouteHandler('./routes/yande.re/post_popular_recent'));
|
||||
router.get('/yande.re/post/popular_recent/:period', lazyloadRouteHandler('./routes/yande.re/post_popular_recent'));
|
||||
router.get('/yande.re/post/popular_recent', lazyloadRouteHandler('./routes/yande.re/post-popular-recent'));
|
||||
router.get('/yande.re/post/popular_recent/:period', lazyloadRouteHandler('./routes/yande.re/post-popular-recent'));
|
||||
|
||||
// EZTV
|
||||
router.get('/eztv/torrents/:imdb_id', lazyloadRouteHandler('./routes/eztv/imdb'));
|
||||
@@ -173,9 +173,9 @@ router.get('/dpu/wlfw/news/:type?', lazyloadRouteHandler('./routes/universities/
|
||||
router.get('/njtech/jwc', lazyloadRouteHandler('./routes/universities/njtech/jwc'));
|
||||
|
||||
// 河海大学
|
||||
router.get('/hhu/libNews', lazyloadRouteHandler('./routes/universities/hhu/libNews'));
|
||||
router.get('/hhu/libNews', lazyloadRouteHandler('./routes/universities/hhu/lib-news'));
|
||||
// 河海大学常州校区
|
||||
router.get('/hhu/libNewsc', lazyloadRouteHandler('./routes/universities/hhu/libNewsc'));
|
||||
router.get('/hhu/libNewsc', lazyloadRouteHandler('./routes/universities/hhu/lib-newsc'));
|
||||
|
||||
// 上海科技大学
|
||||
router.get('/shanghaitech/activity', lazyloadRouteHandler('./routes/universities/shanghaitech/activity'));
|
||||
@@ -197,8 +197,8 @@ router.get('/thu/:type', lazyloadRouteHandler('./routes/universities/thu/index')
|
||||
router.get('/shou/www/:type', lazyloadRouteHandler('./routes/universities/shou/www'));
|
||||
|
||||
// 西南科技大学
|
||||
router.get('/swust/jwc/news', lazyloadRouteHandler('./routes/universities/swust/jwc_news'));
|
||||
router.get('/swust/jwc/notice/:type?', lazyloadRouteHandler('./routes/universities/swust/jwc_notice'));
|
||||
router.get('/swust/jwc/news', lazyloadRouteHandler('./routes/universities/swust/jwc-news'));
|
||||
router.get('/swust/jwc/notice/:type?', lazyloadRouteHandler('./routes/universities/swust/jwc-notice'));
|
||||
router.get('/swust/cs/:type?', lazyloadRouteHandler('./routes/universities/swust/cs'));
|
||||
|
||||
// UTdallas ISSO
|
||||
@@ -308,7 +308,7 @@ router.get('/lyu/news/:type', lazyloadRouteHandler('./routes/universities/lyu/ne
|
||||
|
||||
// 福州大学
|
||||
router.get('/fzu/:type', lazyloadRouteHandler('./routes/universities/fzu/news'));
|
||||
router.get('/fzu_min/:type', lazyloadRouteHandler('./routes/universities/fzu/news_min'));
|
||||
router.get('/fzu_min/:type', lazyloadRouteHandler('./routes/universities/fzu/news-min'));
|
||||
|
||||
// 厦门大学
|
||||
router.get('/xmu/aero/:type', lazyloadRouteHandler('./routes/universities/xmu/aero'));
|
||||
@@ -358,7 +358,7 @@ router.get('/parcel/hermesuk/:tracking', lazyloadRouteHandler('./routes/parcel/h
|
||||
// 数字尾巴
|
||||
router.get('/dgtle', lazyloadRouteHandler('./routes/dgtle/index'));
|
||||
router.get('/dgtle/whale/category/:category', lazyloadRouteHandler('./routes/dgtle/whale'));
|
||||
router.get('/dgtle/whale/rank/:type/:rule', lazyloadRouteHandler('./routes/dgtle/whale_rank'));
|
||||
router.get('/dgtle/whale/rank/:type/:rule', lazyloadRouteHandler('./routes/dgtle/whale-rank'));
|
||||
router.get('/dgtle/trade/:typeId?', lazyloadRouteHandler('./routes/dgtle/trade'));
|
||||
router.get('/dgtle/trade/search/:keyword', lazyloadRouteHandler('./routes/dgtle/keyword'));
|
||||
|
||||
@@ -429,11 +429,11 @@ router.get('/testerhome/newest', lazyloadRouteHandler('./routes/testerhome/newes
|
||||
router.get('/coolbuy/newest', lazyloadRouteHandler('./routes/coolbuy/newest'));
|
||||
|
||||
// MiniFlux
|
||||
router.get('/miniflux/subscription/:parameters?', lazyloadRouteHandler('./routes/miniflux/get_feeds'));
|
||||
router.get('/miniflux/:feeds/:parameters?', lazyloadRouteHandler('./routes/miniflux/get_entries'));
|
||||
router.get('/miniflux/subscription/:parameters?', lazyloadRouteHandler('./routes/miniflux/get-feeds'));
|
||||
router.get('/miniflux/:feeds/:parameters?', lazyloadRouteHandler('./routes/miniflux/get-entries'));
|
||||
|
||||
// 動畫瘋
|
||||
router.get('/anigamer/new_anime', lazyloadRouteHandler('./routes/anigamer/new_anime'));
|
||||
router.get('/anigamer/new_anime', lazyloadRouteHandler('./routes/anigamer/new-anime'));
|
||||
router.get('/anigamer/anime/:sn', lazyloadRouteHandler('./routes/anigamer/anime'));
|
||||
|
||||
// 中国药科大学
|
||||
@@ -567,7 +567,7 @@ router.get('/ui-cn/user/:id', lazyloadRouteHandler('./routes/ui-cn/user'));
|
||||
|
||||
// 一些博客
|
||||
// 敬维-以认真的态度做完美的事情: https://jingwei.link/
|
||||
router.get('/blogs/jingwei.link', lazyloadRouteHandler('./routes/blogs/jingwei_link'));
|
||||
router.get('/blogs/jingwei.link', lazyloadRouteHandler('./routes/blogs/jingwei-link'));
|
||||
|
||||
// 王垠的博客-当然我在扯淡
|
||||
router.get('/blogs/wangyin', lazyloadRouteHandler('./routes/blogs/wangyin'));
|
||||
@@ -695,7 +695,7 @@ router.get('/aqicn/:city/:pollution?', lazyloadRouteHandler('./routes/aqicn/inde
|
||||
// 猫眼电影
|
||||
router.get('/maoyan/hot', lazyloadRouteHandler('./routes/maoyan/hot'));
|
||||
router.get('/maoyan/upcoming', lazyloadRouteHandler('./routes/maoyan/upcoming'));
|
||||
router.get('/maoyan/hotComplete/:orderby?/:ascOrDesc?/:top?', lazyloadRouteHandler('./routes/maoyan/hotComplete'));
|
||||
router.get('/maoyan/hotComplete/:orderby?/:ascOrDesc?/:top?', lazyloadRouteHandler('./routes/maoyan/hot-complete'));
|
||||
|
||||
// 国家退伍士兵信息
|
||||
router.get('/gov/veterans/:type', lazyloadRouteHandler('./routes/gov/veterans/china'));
|
||||
@@ -779,8 +779,8 @@ router.get('/simonsfoundation/recommend', lazyloadRouteHandler('./routes/simonsf
|
||||
router.get('/siren/news', lazyloadRouteHandler('./routes/siren/index'));
|
||||
|
||||
// 学堂在线
|
||||
router.get('/xuetangx/course/:cid/:type', lazyloadRouteHandler('./routes/xuetangx/course_info'));
|
||||
router.get('/xuetangx/course/list/:mode/:credential/:status/:type?', lazyloadRouteHandler('./routes/xuetangx/course_list'));
|
||||
router.get('/xuetangx/course/:cid/:type', lazyloadRouteHandler('./routes/xuetangx/course-info'));
|
||||
router.get('/xuetangx/course/list/:mode/:credential/:status/:type?', lazyloadRouteHandler('./routes/xuetangx/course-list'));
|
||||
|
||||
// 正版中国
|
||||
// router.get('/getitfree/category/:category?', lazyloadRouteHandler('./routes/getitfree/category.js'));
|
||||
@@ -951,11 +951,11 @@ router.get('/emi-nitta/:type', lazyloadRouteHandler('./routes/emi-nitta/home'));
|
||||
router.get('/vscode/marketplace/:type?', lazyloadRouteHandler('./routes/vscode/marketplace'));
|
||||
|
||||
// 饭否
|
||||
router.get('/fanfou/user_timeline/:uid', lazyloadRouteHandler('./routes/fanfou/user_timeline'));
|
||||
router.get('/fanfou/home_timeline', lazyloadRouteHandler('./routes/fanfou/home_timeline'));
|
||||
router.get('/fanfou/user_timeline/:uid', lazyloadRouteHandler('./routes/fanfou/user-timeline'));
|
||||
router.get('/fanfou/home_timeline', lazyloadRouteHandler('./routes/fanfou/home-timeline'));
|
||||
router.get('/fanfou/favorites/:uid', lazyloadRouteHandler('./routes/fanfou/favorites'));
|
||||
router.get('/fanfou/trends', lazyloadRouteHandler('./routes/fanfou/trends'));
|
||||
router.get('/fanfou/public_timeline/:keyword', lazyloadRouteHandler('./routes/fanfou/public_timeline'));
|
||||
router.get('/fanfou/public_timeline/:keyword', lazyloadRouteHandler('./routes/fanfou/public-timeline'));
|
||||
|
||||
// Remote Work
|
||||
router.get('/remote-work/:caty?', lazyloadRouteHandler('./routes/remote-work/index'));
|
||||
@@ -965,7 +965,7 @@ router.get('/chocolatey/software/:name?', lazyloadRouteHandler('./routes/chocola
|
||||
|
||||
// 巴哈姆特
|
||||
router.get('/bahamut/creation/:author/:category?', lazyloadRouteHandler('./routes/bahamut/creation'));
|
||||
router.get('/bahamut/creation_index/:category?/:subcategory?/:type?', lazyloadRouteHandler('./routes/bahamut/creation_index'));
|
||||
router.get('/bahamut/creation_index/:category?/:subcategory?/:type?', lazyloadRouteHandler('./routes/bahamut/creation-index'));
|
||||
|
||||
// CentBrowser
|
||||
router.get('/centbrowser/history', lazyloadRouteHandler('./routes/centbrowser/history'));
|
||||
@@ -1065,7 +1065,7 @@ router.get('/haohaozhu/discover/:keyword?', lazyloadRouteHandler('./routes/haoha
|
||||
|
||||
// 魔法纪录
|
||||
router.get('/magireco/announcements', lazyloadRouteHandler('./routes/magireco/announcements'));
|
||||
router.get('/magireco/event_banner', lazyloadRouteHandler('./routes/magireco/event_banner'));
|
||||
router.get('/magireco/event_banner', lazyloadRouteHandler('./routes/magireco/event-banner'));
|
||||
|
||||
// 我有一片芝麻地
|
||||
router.get('/blogs/hedwig/:type', lazyloadRouteHandler('./routes/blogs/hedwig'));
|
||||
@@ -1450,7 +1450,7 @@ router.get('/dw/:lang?/:caty?', lazyloadRouteHandler('./routes/dw/index'));
|
||||
router.get('/citavi/:caty?', lazyloadRouteHandler('./routes/citavi/index'));
|
||||
|
||||
// Sesame
|
||||
router.get('/sesame/release_notes', lazyloadRouteHandler('./routes/sesame/release_notes'));
|
||||
router.get('/sesame/release_notes', lazyloadRouteHandler('./routes/sesame/release-notes'));
|
||||
|
||||
// QNAP
|
||||
router.get('/qnap/release-notes/:id', lazyloadRouteHandler('./routes/qnap/release-notes'));
|
||||
@@ -1475,7 +1475,7 @@ router.get('/grandchallenge/challenges', lazyloadRouteHandler('./routes/grandcha
|
||||
router.get('/nwpu/:column', lazyloadRouteHandler('./routes/nwpu/index'));
|
||||
|
||||
// 美国联邦最高法院
|
||||
router.get('/us/supremecourt/argument_audio/:year?', lazyloadRouteHandler('./routes/us/supremecourt/argument_audio'));
|
||||
router.get('/us/supremecourt/argument_audio/:year?', lazyloadRouteHandler('./routes/us/supremecourt/argument-audio'));
|
||||
|
||||
// 优设网
|
||||
router.get('/uisdc/hangye/:caty?', lazyloadRouteHandler('./routes/uisdc/hangye'));
|
||||
@@ -1574,7 +1574,7 @@ router.get('/marginnote/tag/:id?', lazyloadRouteHandler('./routes/marginnote/tag
|
||||
router.get('/asml/press-releases', lazyloadRouteHandler('./routes/asml/press-releases'));
|
||||
|
||||
// 有趣天文奇观
|
||||
router.get('/interesting-sky/astronomical_events/:year?', lazyloadRouteHandler('./routes/interesting-sky/astronomical_events'));
|
||||
router.get('/interesting-sky/astronomical_events/:year?', lazyloadRouteHandler('./routes/interesting-sky/astronomical-events'));
|
||||
router.get('/interesting-sky/recent-interesting', lazyloadRouteHandler('./routes/interesting-sky/recent-interesting'));
|
||||
router.get('/interesting-sky', lazyloadRouteHandler('./routes/interesting-sky/index'));
|
||||
|
||||
@@ -1704,8 +1704,8 @@ router.get('/furaffinity/journals/:username', lazyloadRouteHandler('./routes/fur
|
||||
router.get('/furaffinity/gallery/:username/:nsfw?', lazyloadRouteHandler('./routes/furaffinity/gallery'));
|
||||
router.get('/furaffinity/scraps/:username/:nsfw?', lazyloadRouteHandler('./routes/furaffinity/scraps'));
|
||||
router.get('/furaffinity/favorites/:username/:nsfw?', lazyloadRouteHandler('./routes/furaffinity/favorites'));
|
||||
router.get('/furaffinity/submission_comments/:id', lazyloadRouteHandler('./routes/furaffinity/submission_comments'));
|
||||
router.get('/furaffinity/journal_comments/:id', lazyloadRouteHandler('./routes/furaffinity/journal_comments'));
|
||||
router.get('/furaffinity/submission_comments/:id', lazyloadRouteHandler('./routes/furaffinity/submission-comments'));
|
||||
router.get('/furaffinity/journal_comments/:id', lazyloadRouteHandler('./routes/furaffinity/journal-comments'));
|
||||
|
||||
// Trakt.tv
|
||||
router.get('/trakt/collection/:username/:type?', lazyloadRouteHandler('./routes/trakt/collection'));
|
||||
|
||||
@@ -17,7 +17,7 @@ module.exports = async (ctx) => {
|
||||
description: `<img src="${$(item).find('img').attr('src')}" /> <br>
|
||||
${$(item).find('div.p-row').text()}`,
|
||||
link: $(item).find('h3 > a').attr('href'),
|
||||
pubDate: new Date($(item).find('span.fr.time').text().trim().substr(0, 4), $(item).find('span.fr.time').text().trim().substr(5, 2), $(item).find('span.fr.time').text().trim().substr(8, 4)).toUTCString(),
|
||||
pubDate: new Date($(item).find('span.fr.time').text().trim().slice(0, 4), $(item).find('span.fr.time').text().trim().slice(5, 7), $(item).find('span.fr.time').text().trim().slice(8, 12)).toUTCString(),
|
||||
}))
|
||||
.get(),
|
||||
};
|
||||
|
||||
@@ -32,7 +32,7 @@ module.exports = async (ctx) => {
|
||||
|
||||
const cache = await ctx.cache.get(link);
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
|
||||
const description = await ProcessFeed(link);
|
||||
@@ -46,7 +46,7 @@ module.exports = async (ctx) => {
|
||||
};
|
||||
|
||||
ctx.cache.set(link, JSON.stringify(single));
|
||||
return Promise.resolve(single);
|
||||
return single;
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ module.exports = async (ctx) => {
|
||||
method: 'get',
|
||||
url: currentUrl,
|
||||
});
|
||||
const data = JSON.parse(response.data.substr('var alertData ='.length, response.data.length + 1));
|
||||
const data = JSON.parse(response.data.slice('var alertData ='.length, 'var alertData ='.length + response.data.length + 1));
|
||||
|
||||
const list = data.map((item) => ({
|
||||
title: item.headline,
|
||||
|
||||
@@ -22,7 +22,7 @@ module.exports = async (ctx) => {
|
||||
list.map(async (link) => {
|
||||
const cache = await ctx.cache.get(link);
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
|
||||
const response = await got({
|
||||
@@ -47,7 +47,7 @@ module.exports = async (ctx) => {
|
||||
const $el = $(element);
|
||||
const img_original_data = $el.attr('data-original');
|
||||
const img_src = $el.attr('src');
|
||||
if (typeof img_src === 'undefined' && img_original_data) {
|
||||
if (img_src === undefined && img_original_data) {
|
||||
$el.attr('src', img_original_data);
|
||||
}
|
||||
});
|
||||
@@ -62,7 +62,7 @@ module.exports = async (ctx) => {
|
||||
};
|
||||
|
||||
ctx.cache.set(link, JSON.stringify(single));
|
||||
return Promise.resolve(single);
|
||||
return single;
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ module.exports = async (ctx) => {
|
||||
const address = $(item).attr('href');
|
||||
const cache = await ctx.cache.get(address);
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
const res = await got.get(address);
|
||||
const capture = cheerio.load(res.data);
|
||||
@@ -33,7 +33,7 @@ module.exports = async (ctx) => {
|
||||
intro +
|
||||
capture('.transcript__inner')
|
||||
.html()
|
||||
.replace(/<p>\[?<em>\(?The above text.*this podcast.*?em.*?p>/g, '');
|
||||
.replaceAll(/<p>\[?<em>\(?The above text.*this podcast.*?em.*?p>/g, '');
|
||||
const track = capture('.podcasts__media > div > a').attr('href');
|
||||
const single = {
|
||||
title,
|
||||
@@ -46,7 +46,7 @@ module.exports = async (ctx) => {
|
||||
pubDate: new Date(time).toUTCString(),
|
||||
};
|
||||
ctx.cache.set(address, JSON.stringify(single));
|
||||
return Promise.resolve(single);
|
||||
return single;
|
||||
})
|
||||
);
|
||||
ctx.state.data = {
|
||||
|
||||
@@ -29,13 +29,13 @@ module.exports = async (ctx) => {
|
||||
.map((item) => {
|
||||
switch (item.bodyType) {
|
||||
case 1:
|
||||
return `<p>${item.text.replace(/\n/gm, '<br/>')}</p>`;
|
||||
return `<p>${item.text.replaceAll(/\n/gm, '<br/>')}</p>`;
|
||||
case 2:
|
||||
return `<img src="${item.image}">`;
|
||||
case 3:
|
||||
return `<img src="${item.image}">`;
|
||||
case 4:
|
||||
return `<blockquote>${item.comment.user.name}:<br/>${item.comment.comment.body.replace(/\n/gm, '<br/>')}</blockquote>`;
|
||||
return `<blockquote>${item.comment.user.name}:<br/>${item.comment.comment.body.replaceAll(/\n/gm, '<br/>')}</blockquote>`;
|
||||
case 7:
|
||||
return `<blockquote>${item.talk.name}:<br/>${GetContent(item.post)}</blockquote>`;
|
||||
case 8:
|
||||
@@ -49,7 +49,7 @@ module.exports = async (ctx) => {
|
||||
const GetTitle = (post) => {
|
||||
const texts = post.body.filter((s) => s.bodyType === 1);
|
||||
const type_name = postTypes[post.postType];
|
||||
return texts.length !== 0 ? texts[0].text.split('\n')[0] : type_name;
|
||||
return texts.length === 0 ? type_name : texts[0].text.split('\n')[0];
|
||||
};
|
||||
|
||||
const ProcessFeed = (data) =>
|
||||
|
||||
@@ -20,7 +20,7 @@ module.exports = async (ctx) => {
|
||||
.map(async (itemUrl) => {
|
||||
const cache = await ctx.cache.get(itemUrl);
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
|
||||
const response = await got.get(itemUrl);
|
||||
@@ -34,7 +34,7 @@ module.exports = async (ctx) => {
|
||||
pubDate: new Date($('article header .entry-meta time').text()).toUTCString(),
|
||||
};
|
||||
ctx.cache.set(itemUrl, JSON.stringify(single));
|
||||
return Promise.resolve(single);
|
||||
return single;
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ module.exports = async (ctx) => {
|
||||
.map(async (_, item) => {
|
||||
item = $(item);
|
||||
|
||||
const year = item.find('span').text().replace(/\(|\)/g, '');
|
||||
const year = item.find('span').text().replaceAll(/\(|\)/g, '');
|
||||
const pubDate = new Date(`${year}-12-31`).toUTCString();
|
||||
|
||||
const winnersUrls = [];
|
||||
@@ -47,7 +47,7 @@ module.exports = async (ctx) => {
|
||||
winnerDescription += image + column.html();
|
||||
}
|
||||
|
||||
return Promise.resolve(winnerDescription);
|
||||
return winnerDescription;
|
||||
});
|
||||
|
||||
return {
|
||||
|
||||
@@ -25,7 +25,7 @@ module.exports = async (ctx) => {
|
||||
|
||||
const cache = await ctx.cache.get(link);
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
|
||||
const response = await got({
|
||||
@@ -41,7 +41,7 @@ module.exports = async (ctx) => {
|
||||
link,
|
||||
};
|
||||
ctx.cache.set(link, JSON.stringify(single));
|
||||
return Promise.resolve(single);
|
||||
return single;
|
||||
})
|
||||
);
|
||||
ctx.state.data = { title: '路由器交流', link: baseUrl, item: out };
|
||||
|
||||
@@ -18,12 +18,7 @@ const config = {
|
||||
};
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
let cfg;
|
||||
if (ctx.params.type) {
|
||||
cfg = config[ctx.params.type];
|
||||
} else {
|
||||
cfg = config.index;
|
||||
}
|
||||
const cfg = ctx.params.type ? config[ctx.params.type] : config.index;
|
||||
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
|
||||
@@ -6,11 +6,7 @@ module.exports = async (ctx) => {
|
||||
|
||||
let url = 'https://api.yanxishe.com/api?page=1&size=30&parent_tag=';
|
||||
|
||||
if (id === 'all') {
|
||||
url += '&tag=';
|
||||
} else {
|
||||
url += `&tag=${id}`;
|
||||
}
|
||||
url += id === 'all' ? '&tag=' : `&tag=${id}`;
|
||||
if (sort === 'hot') {
|
||||
url += '&is_hot=1&is_recommend=0';
|
||||
} else if (sort === 'recommend') {
|
||||
@@ -35,11 +31,7 @@ module.exports = async (ctx) => {
|
||||
case 'blog': // 博客
|
||||
description = data.content;
|
||||
author = data.user.nickname;
|
||||
if (data.relation_special) {
|
||||
link = `https://www.yanxishe.com/columnDetail/${id}`;
|
||||
} else {
|
||||
link = `https://www.yanxishe.com/blogDetail/${id}`;
|
||||
}
|
||||
link = data.relation_special ? `https://www.yanxishe.com/columnDetail/${id}` : `https://www.yanxishe.com/blogDetail/${id}`;
|
||||
break;
|
||||
case 'question': // 问答
|
||||
description = data.content;
|
||||
@@ -48,9 +40,9 @@ module.exports = async (ctx) => {
|
||||
break;
|
||||
case 'article': // 翻译
|
||||
description = `<table><tr><td width="50%"> ${data.title} </td><td> ${data.zh_title} </td></tr>`;
|
||||
data.paragraphs.forEach((element) => {
|
||||
for (const element of data.paragraphs) {
|
||||
description += `<tr><td> ${element.content} </td><td> ${element.zh_content.content} </td></tr>`;
|
||||
});
|
||||
}
|
||||
description += `</table>
|
||||
<style>
|
||||
table,
|
||||
@@ -89,17 +81,29 @@ module.exports = async (ctx) => {
|
||||
response.data.data.all.map(async (item) => {
|
||||
let itemUrl = `https://api.yanxishe.com/api/sthread/${item.id}?token=null`;
|
||||
|
||||
if (item.type === 'blog') {
|
||||
itemUrl += '&type=null';
|
||||
} else if (item.type === 'article') {
|
||||
itemUrl = `https://api.yanxishe.com/api/stranslate/article/${item.id}?token=null&type=null`;
|
||||
} else if (item.type === 'paper') {
|
||||
itemUrl = `https://api.yanxishe.com/api/spaper/detail?token=null&id=${item.id}`;
|
||||
switch (item.type) {
|
||||
case 'blog':
|
||||
itemUrl += '&type=null';
|
||||
|
||||
break;
|
||||
|
||||
case 'article':
|
||||
itemUrl = `https://api.yanxishe.com/api/stranslate/article/${item.id}?token=null&type=null`;
|
||||
|
||||
break;
|
||||
|
||||
case 'paper':
|
||||
itemUrl = `https://api.yanxishe.com/api/spaper/detail?token=null&id=${item.id}`;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error(`Unknown type: ${item.type}`);
|
||||
}
|
||||
|
||||
const cache = await ctx.cache.get(itemUrl);
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
|
||||
const response = await got({
|
||||
@@ -112,12 +116,12 @@ module.exports = async (ctx) => {
|
||||
const single = {
|
||||
title: item.zh_title,
|
||||
description: result.description,
|
||||
pubDate: new Date(parseFloat(item.published_time + '000')).toUTCString(),
|
||||
pubDate: new Date(Number.parseFloat(item.published_time + '000')).toUTCString(),
|
||||
link: result.link,
|
||||
author: result.author,
|
||||
};
|
||||
ctx.cache.set(itemUrl, JSON.stringify(single));
|
||||
return Promise.resolve(single);
|
||||
return single;
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const utils = require('./utils');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const currentUrl = `search/${ctx.params.model}/tags/${ctx.params.keyword ? ctx.params.keyword : ''}${ctx.params.sortBy ? '?sortby=' + ctx.params.sortBy : ''}`;
|
||||
const currentUrl = `search/${ctx.params.model}/tags/${ctx.params.keyword ?? ''}${ctx.params.sortBy ? '?sortby=' + ctx.params.sortBy : ''}`;
|
||||
|
||||
ctx.state.data = await utils(ctx, currentUrl);
|
||||
};
|
||||
|
||||
@@ -5,7 +5,7 @@ const url = 'https://download.amd.com/drivers/xml/driver_09_us.xml';
|
||||
|
||||
// 06/10/2020 -> Wed Jun 10 2020 00:00:00
|
||||
function convertDate(dateStr) {
|
||||
const [month, day, year] = dateStr.split('/').map((x) => parseInt(x, 10));
|
||||
const [month, day, year] = dateStr.split('/').map((x) => Number.parseInt(x, 10));
|
||||
const date = new Date();
|
||||
date.setFullYear(year, month - 1, day);
|
||||
date.setHours(0, 0, 0, 0);
|
||||
@@ -89,14 +89,14 @@ module.exports = async (ctx) => {
|
||||
if (whql) {
|
||||
try {
|
||||
item.push(versionToRss(whql, false));
|
||||
} catch (e) {
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
if (beta) {
|
||||
try {
|
||||
item.push(versionToRss(beta, true));
|
||||
} catch (e) {
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ module.exports = async (ctx) => {
|
||||
const list = $('table.list tr');
|
||||
|
||||
// get how many new-books. amount in this page is 50
|
||||
let count = parseInt(ctx.params.count);
|
||||
let count = Number.parseInt(ctx.params.count);
|
||||
if (Number.isNaN(count) || count < 1) {
|
||||
count = 10; // default count of new-book list
|
||||
} else if (count > 50) {
|
||||
@@ -44,35 +44,35 @@ module.exports = async (ctx) => {
|
||||
for (let i = 0; i < count; ++i) {
|
||||
const $ = cheerio.load(cards[i]);
|
||||
const link = $('meta[property="og:url"]').attr('content');
|
||||
const link_dir = link.replace(/\/[^/]*$/g, '/');
|
||||
const link_dir = link.replaceAll(/\/[^/]*$/g, '/');
|
||||
const title_info = $('table[summary="タイトルデータ"] > tbody > tr');
|
||||
let author = '';
|
||||
let title = '';
|
||||
let title_sub = '';
|
||||
for (let j = 0; j < title_info.length; ++j) {
|
||||
const tmp = entities.decodeXML($(title_info[j]).html()); // should convert from escaped to unicode
|
||||
for (const element of title_info) {
|
||||
const tmp = entities.decodeXML($(element).html()); // should convert from escaped to unicode
|
||||
if (tmp.includes('作品名:')) {
|
||||
title = $(title_info[j]).find('td:nth-child(2)').text();
|
||||
title = $(element).find('td:nth-child(2)').text();
|
||||
}
|
||||
if (tmp.includes('副題:')) {
|
||||
title_sub = $(title_info[j]).find('td:nth-child(2)').text();
|
||||
title_sub = $(element).find('td:nth-child(2)').text();
|
||||
}
|
||||
if (tmp.includes('著者名:')) {
|
||||
author = $(title_info[j]).find('td:nth-child(2)').text();
|
||||
author = $(element).find('td:nth-child(2)').text();
|
||||
}
|
||||
}
|
||||
if (title_sub !== '') {
|
||||
title += ' —— ' + title_sub;
|
||||
}
|
||||
const pub_date_raw = $('table[summary="底本データ"] > tbody > tr:nth-child(3) > td:nth-child(2)').text();
|
||||
const pub_date_num = pub_date_raw.replace(/(.*)|日/g, '').replace(/[年月]/g, '-');
|
||||
const pub_date_num = pub_date_raw.replaceAll(/(.*)|日/g, '').replaceAll(/[年月]/g, '-');
|
||||
const pub_date = new Date(pub_date_num).toUTCString();
|
||||
const full_text_relative_link = $('table.download > tbody > tr:nth-child(3) > td:nth-child(3) > a').attr('href');
|
||||
const full_text_link = link_dir + full_text_relative_link;
|
||||
const full_text_link_html = '<a href="' + full_text_link + '">いますぐXHTML版で読む</a><br>';
|
||||
const summury = $('table[summary="作品データ"]')
|
||||
.html()
|
||||
.replace(/href="/g, 'href="' + link_dir);
|
||||
.replaceAll('href="', 'href="' + link_dir);
|
||||
|
||||
const item = {
|
||||
title,
|
||||
|
||||
@@ -15,11 +15,11 @@ module.exports = async (ctx) => {
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
if (ctx.params.caty === 'mostwanted') {
|
||||
times.forEach((i) => {
|
||||
for (const i of times) {
|
||||
if (i !== ctx.params.time) {
|
||||
$(`#charts-${i}`).remove();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$('i,img.play-icon-small').remove();
|
||||
|
||||
@@ -21,7 +21,7 @@ module.exports = async (ctx) => {
|
||||
feed.items.map(async (item) => {
|
||||
const cache = await ctx.cache.get(item.link);
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
|
||||
const description = await ProcessFeed(item.link);
|
||||
@@ -34,7 +34,7 @@ module.exports = async (ctx) => {
|
||||
author: item.author,
|
||||
};
|
||||
ctx.cache.set(item.link, JSON.stringify(single));
|
||||
return Promise.resolve(single);
|
||||
return single;
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
@@ -32,11 +32,7 @@ module.exports = async (ctx) => {
|
||||
let currentUrl;
|
||||
if (genre) {
|
||||
if (category) {
|
||||
if (category in categories) {
|
||||
currentUrl = `${rootUrl}${categories[category]}`;
|
||||
} else {
|
||||
currentUrl = `${rootUrl}/${genre}/list/${category}.html`;
|
||||
}
|
||||
currentUrl = category in categories ? `${rootUrl}${categories[category]}` : `${rootUrl}/${genre}/list/${category}.html`;
|
||||
} else {
|
||||
currentUrl = `${rootUrl}/${genre}`;
|
||||
}
|
||||
@@ -60,7 +56,7 @@ module.exports = async (ctx) => {
|
||||
const link = item.attr('href');
|
||||
|
||||
return {
|
||||
link: link.indexOf('//') < 0 ? `${rootUrl}${link}` : `https:${link}`,
|
||||
link: link.includes('//') ? `https:${link}` : `${rootUrl}${link}`,
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
@@ -16,7 +16,7 @@ module.exports = async (ctx) => {
|
||||
const cache = await ctx.cache.get(link);
|
||||
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
|
||||
const response = await got.get(link);
|
||||
@@ -57,7 +57,7 @@ module.exports = async (ctx) => {
|
||||
link,
|
||||
};
|
||||
ctx.cache.set(link, JSON.stringify(single));
|
||||
return Promise.resolve(single);
|
||||
return single;
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const got = require('@/utils/got');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const keyword = ctx.params.keyword ? ctx.params.keyword : '';
|
||||
const keyword = ctx.params.keyword ?? '';
|
||||
|
||||
let default_order, default_time;
|
||||
if (keyword) {
|
||||
@@ -12,9 +12,9 @@ module.exports = async (ctx) => {
|
||||
default_time = 'm';
|
||||
}
|
||||
|
||||
const order = ctx.params.order ? ctx.params.order : default_order;
|
||||
const time = ctx.params.time ? ctx.params.time : default_time;
|
||||
const top = ctx.params.top ? ctx.params.top : 30;
|
||||
const order = ctx.params.order ?? default_order;
|
||||
const time = ctx.params.time ?? default_time;
|
||||
const top = ctx.params.top ?? 30;
|
||||
const url = keyword ? `https://api.avgle.com/v1/search/${keyword}/0` : `https://api.avgle.com/v1/videos/0`;
|
||||
|
||||
const response = await got({
|
||||
|
||||
@@ -3,80 +3,73 @@ const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const { type, tag } = ctx.params || '';
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: `https://axisstudiosgroup.com/${type}/${tag}`,
|
||||
});
|
||||
const response = await got(`https://axisstudiosgroup.com/${type}/${tag}`);
|
||||
const data = response.data;
|
||||
const $ = cheerio.load(data); // 使用 cheerio 加载返回的 HTML
|
||||
const list = $('a.overlay-link').get().slice(0, 13);
|
||||
const articledata = await Promise.all(
|
||||
list.map(async (item) => {
|
||||
const link = `https://axisstudiosgroup.com${$(item)
|
||||
.attr('href')
|
||||
.replace(/https:/, '')}`;
|
||||
|
||||
const cache = await ctx.cache.get(link);
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
}
|
||||
|
||||
const response2 = await got({
|
||||
method: 'get',
|
||||
url: link,
|
||||
});
|
||||
|
||||
const articleHtml = response2.data;
|
||||
const $2 = cheerio.load(articleHtml);
|
||||
|
||||
$2('.slider-nav').remove(); // 图片导航
|
||||
$2('.social-wrapper').remove(); // 社交按钮
|
||||
$2('source').remove(); // 莫名其妙的图片
|
||||
$2('video').remove(); // 视频标签
|
||||
$2('button').remove(); // 按钮
|
||||
$2('div.modal.fade').remove(); // 莫名奇妙的图片
|
||||
$2('i').remove();
|
||||
|
||||
const youtube = $2('.mcdr.playlist-control a').attr('data-video-type') === 'video/youtube' ? $2('.mcdr.playlist-control a').attr('data-video-url').replace('https://www.youtube.com/watch?v=', '') : '';
|
||||
const mp4 = $2('.mcdr.playlist-control a').attr('data-video-type') === 'video/mp4' ? $2('.mcdr.playlist-control a').attr('data-video-url') : '';
|
||||
|
||||
const content = $2('.container-fluid>div:nth-child(2)')
|
||||
.html()
|
||||
.replace(/<video*.+poster=/g, '<video controls="controls" poster=')
|
||||
.replace(/<.?picture>/g, '')
|
||||
.replace(/<picture*.+>/g, '')
|
||||
.replace(/<div*.+>/g, '')
|
||||
.replace(/<.?div>/g, '')
|
||||
.replace(/<!--*.+-->/g, '');
|
||||
const single = {
|
||||
describe: content,
|
||||
title: $2('.overlay-content').find('h1').text(),
|
||||
link,
|
||||
mp4,
|
||||
youtube,
|
||||
const list = $('a.overlay-link')
|
||||
.toArray()
|
||||
.map((item) => {
|
||||
item = $(item);
|
||||
return {
|
||||
title: item.find('h2').text().trim(),
|
||||
link: new URL(item.attr('href'), 'https://axisstudiosgroup.com').href,
|
||||
};
|
||||
ctx.cache.set(link, JSON.stringify(single));
|
||||
return Promise.resolve(single);
|
||||
})
|
||||
});
|
||||
|
||||
const items = await Promise.all(
|
||||
list.map((item) =>
|
||||
ctx.cache.tryGet(item.link, async () => {
|
||||
const response2 = await got(item.link);
|
||||
|
||||
const $2 = cheerio.load(response2.data);
|
||||
|
||||
$2('.slider-nav').remove(); // 图片导航
|
||||
$2('.social-wrapper').remove(); // 社交按钮
|
||||
$2('source').remove(); // 莫名其妙的图片
|
||||
$2('video').remove(); // 视频标签
|
||||
$2('button').remove(); // 按钮
|
||||
$2('div.modal.fade').remove(); // 莫名奇妙的图片
|
||||
$2('i').remove();
|
||||
$2('*')
|
||||
.contents()
|
||||
.filter((_, el) => el.type === 'comment')
|
||||
.remove();
|
||||
|
||||
const mcdrPlaylistControl = $2('.mcdr.playlist-control a');
|
||||
const youtube = mcdrPlaylistControl.data('video-type') === 'video/youtube' ? mcdrPlaylistControl.data('video-url').replace('https://www.youtube.com/watch?v=', '') : '';
|
||||
const mp4 = mcdrPlaylistControl.data('video-type') === 'video/mp4' ? mcdrPlaylistControl.data('video-url') : '';
|
||||
|
||||
const content = $2('.container-fluid>div:nth-child(2)');
|
||||
content.find('video').attr('controls', 'controls');
|
||||
content.find('picture').each((_, el) => {
|
||||
el = $2(el);
|
||||
el.replaceWith(el.html());
|
||||
});
|
||||
content.find('div').each((_, el) => {
|
||||
el = $2(el);
|
||||
if (el.children().length) {
|
||||
el.replaceWith(el.children());
|
||||
}
|
||||
});
|
||||
|
||||
let video = '';
|
||||
if (mp4) {
|
||||
video = `<video width="100%" controls="controls" width="640" height="360" source src="${mp4}" type="video/mp4"></video><br>`;
|
||||
}
|
||||
if (youtube) {
|
||||
video = `<iframe id="ytplayer" type="text/html" width="640" height="360" src='https://www.youtube-nocookie.com/embed/${youtube}' frameborder='0' webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe><br>`;
|
||||
}
|
||||
|
||||
item.description = video + content.html();
|
||||
return item;
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: `Axis Studios | ${type} ${tag ? tag : ''}`,
|
||||
title: `Axis Studios | ${type} ${tag ?? ''}`,
|
||||
link: 'http://axisstudiosgroup.com',
|
||||
description: $('description').text(),
|
||||
item: list.map((item, index) => {
|
||||
let video = '';
|
||||
if (articledata[index].mp4) {
|
||||
video = `<video width="100%" controls="controls" width="640" height="360" source src="${articledata[index].mp4}" type="video/mp4"></video><br>`;
|
||||
}
|
||||
if (articledata[index].youtube) {
|
||||
video = `<iframe id="ytplayer" type="text/html" width="640" height="360" src='https://youtube.com/embed/${articledata[index].youtube}' frameborder='0' webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe><br>`;
|
||||
}
|
||||
return {
|
||||
title: articledata[index].title,
|
||||
description: `${video}+${articledata[index].describe}`,
|
||||
link: articledata[index].link,
|
||||
};
|
||||
}),
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -10,16 +10,34 @@ module.exports = async (ctx) => {
|
||||
|
||||
let link = `https://www.baby-kingdom.com/forum.php?mod=forumdisplay&fid=${id}`;
|
||||
|
||||
if (order === 'dateline') {
|
||||
link += '&filter=author&orderby=dateline';
|
||||
} else if (order === 'reply') {
|
||||
link += '&filter=reply&orderby=replies';
|
||||
} else if (order === 'view') {
|
||||
link += '&filter=reply&orderby=views';
|
||||
} else if (order === 'lastpost') {
|
||||
link += '&filter=lastpost&orderby=lastpost';
|
||||
} else if (order === 'heat') {
|
||||
link += '&filter=heat&orderby=heats';
|
||||
switch (order) {
|
||||
case 'dateline':
|
||||
link += '&filter=author&orderby=dateline';
|
||||
|
||||
break;
|
||||
|
||||
case 'reply':
|
||||
link += '&filter=reply&orderby=replies';
|
||||
|
||||
break;
|
||||
|
||||
case 'view':
|
||||
link += '&filter=reply&orderby=views';
|
||||
|
||||
break;
|
||||
|
||||
case 'lastpost':
|
||||
link += '&filter=lastpost&orderby=lastpost';
|
||||
|
||||
break;
|
||||
|
||||
case 'heat':
|
||||
link += '&filter=heat&orderby=heats';
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
const response = await got.get(link);
|
||||
|
||||
@@ -57,16 +57,16 @@ const subcategory_map = {
|
||||
};
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const type = ctx.params.type ? ctx.params.type : '1';
|
||||
const category = ctx.params.category ? ctx.params.category : '0';
|
||||
const subcategory = ctx.params.subcategory ? ctx.params.subcategory : '0';
|
||||
const type = ctx.params.type ?? '1';
|
||||
const category = ctx.params.category ?? '0';
|
||||
const subcategory = ctx.params.subcategory ?? '0';
|
||||
|
||||
const url = `https://home.gamer.com.tw/index.php?k1=${category}&k2=${subcategory}&vt=${type}&sm=3`;
|
||||
|
||||
const { items } = await utils.ProcessFeed(url, ctx);
|
||||
|
||||
ctx.state.data = {
|
||||
title: `巴哈姆特创作大厅${category !== '0' ? ' - ' + category_map[category] : ''}${subcategory !== '0' ? ' - ' + subcategory_map[subcategory] : ''} - ${type_map[type]}`,
|
||||
title: `巴哈姆特创作大厅${category === '0' ? '' : ' - ' + category_map[category]}${subcategory === '0' ? '' : ' - ' + subcategory_map[subcategory]} - ${type_map[type]}`,
|
||||
link: url,
|
||||
item: items,
|
||||
};
|
||||
@@ -16,8 +16,8 @@ module.exports = {
|
||||
const content = $('.MSG-list8C');
|
||||
|
||||
const images = $('img');
|
||||
for (let k = 0; k < images.length; k++) {
|
||||
$(images[k]).attr('src', $(images[k]).attr('data-src'));
|
||||
for (const image of images) {
|
||||
$(image).attr('src', $(image).attr('data-src'));
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -35,7 +35,7 @@ module.exports = {
|
||||
|
||||
const cache = await ctx.cache.get(link);
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
|
||||
const topic = {
|
||||
@@ -49,14 +49,14 @@ module.exports = {
|
||||
const detail_response = await got.get(link);
|
||||
const result = parseContent(detail_response.data);
|
||||
if (!result.description) {
|
||||
return Promise.resolve('');
|
||||
return '';
|
||||
}
|
||||
topic.description = result.description;
|
||||
} catch (err) {
|
||||
return Promise.resolve('');
|
||||
} catch {
|
||||
return '';
|
||||
}
|
||||
ctx.cache.set(link, JSON.stringify(topic));
|
||||
return Promise.resolve(topic);
|
||||
return topic;
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ module.exports = async (ctx) => {
|
||||
const lang = ctx.params.lang || 'en';
|
||||
const id = ctx.params.id || 'bandizip';
|
||||
if (!isValidHost(lang)) {
|
||||
throw Error('Invalid language code');
|
||||
throw new Error('Invalid language code');
|
||||
}
|
||||
|
||||
const rootUrl = `https://${lang}.bandisoft.com`;
|
||||
|
||||
@@ -29,7 +29,7 @@ module.exports = async (ctx) => {
|
||||
|
||||
const cache = await ctx.cache.get(itemUrl);
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
|
||||
const response = await got.get(itemUrl);
|
||||
@@ -44,7 +44,7 @@ module.exports = async (ctx) => {
|
||||
pubDate: new Date(date).toUTCString(),
|
||||
};
|
||||
ctx.cache.set(itemUrl, JSON.stringify(single));
|
||||
return Promise.resolve(single);
|
||||
return single;
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ module.exports = async (ctx) => {
|
||||
const time = $('.Blog-meta-item--date').text();
|
||||
const cache = await ctx.cache.get(address);
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
const res = await got.get(address);
|
||||
const capture = cheerio.load(res.data);
|
||||
@@ -30,7 +30,7 @@ module.exports = async (ctx) => {
|
||||
pubDate: new Date(time).toUTCString(),
|
||||
};
|
||||
ctx.cache.set(address, JSON.stringify(single));
|
||||
return Promise.resolve(single);
|
||||
return single;
|
||||
})
|
||||
);
|
||||
ctx.state.data = {
|
||||
|
||||
@@ -24,7 +24,7 @@ module.exports = async (ctx) => {
|
||||
|
||||
return {
|
||||
title: item.text(),
|
||||
link: link.indexOf('http') > -1 ? link : `${rootUrl}${link}`,
|
||||
link: link.includes('http') ? link : `${rootUrl}${link}`,
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
@@ -16,7 +16,7 @@ module.exports = async (ctx) => {
|
||||
const itemUrl = $('a').attr('href');
|
||||
const cache = await ctx.cache.get(itemUrl);
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
|
||||
const responses = await got.get(itemUrl);
|
||||
@@ -32,7 +32,7 @@ module.exports = async (ctx) => {
|
||||
description: $d('#contentStr').html(),
|
||||
};
|
||||
ctx.cache.set(itemUrl, JSON.stringify(single));
|
||||
return Promise.resolve(single);
|
||||
return single;
|
||||
})
|
||||
);
|
||||
ctx.state.data = {
|
||||
|
||||
@@ -9,7 +9,7 @@ const { isValidHost } = require('@/utils/valid-host');
|
||||
module.exports = async (ctx) => {
|
||||
const type = ctx.params.type;
|
||||
if (!isValidHost(type)) {
|
||||
throw Error('Invalid type');
|
||||
throw new Error('Invalid type');
|
||||
}
|
||||
|
||||
const url = `https://${type}.hedwig.pub`;
|
||||
@@ -23,9 +23,9 @@ module.exports = async (ctx) => {
|
||||
|
||||
const list = content.props.pageProps.issuesByNewsletter.map((item) => {
|
||||
let description = '';
|
||||
item.blocks.forEach((block) => {
|
||||
for (const block of item.blocks) {
|
||||
description += md.render(block.markdown.text);
|
||||
});
|
||||
}
|
||||
return {
|
||||
title: item.subject,
|
||||
description,
|
||||
|
||||
@@ -12,7 +12,7 @@ module.exports = async (ctx) => {
|
||||
const element = $(e);
|
||||
const title = element.find('a').text();
|
||||
const link = url + element.find('a').attr('href');
|
||||
const dateraw = /\d{4}\/\d{2}\/\d{2}/.exec(link)[0];
|
||||
const dateraw = /\d{4}(?:\/\d{2}){2}/.exec(link)[0];
|
||||
|
||||
return {
|
||||
title,
|
||||
@@ -30,7 +30,7 @@ module.exports = async (ctx) => {
|
||||
|
||||
const cache = await ctx.cache.get(link);
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
|
||||
const itemReponse = await got.get(link);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
const parser = require('@/utils/rss-parser');
|
||||
const config = require('@/config').value;
|
||||
const allowDomain = ['lawrence.code.blog'];
|
||||
const allowDomain = new Set(['lawrence.code.blog']);
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
if (!config.feature.allow_user_supply_unsafe_domain && !allowDomain.includes(ctx.params.domain)) {
|
||||
if (!config.feature.allow_user_supply_unsafe_domain && !allowDomain.has(ctx.params.domain)) {
|
||||
ctx.throw(403, `This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.`);
|
||||
}
|
||||
|
||||
@@ -16,12 +16,12 @@ module.exports = async (ctx) => {
|
||||
feed.items.map(async (item) => {
|
||||
const cache = await ctx.cache.get(item.link);
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
const description =
|
||||
scheme === 'https' || !cdn
|
||||
? item['content:encoded']
|
||||
: item['content:encoded'].replace(/(?<=<img.*src=")(.*)(?=".*\/>)/g, (match, p) => {
|
||||
: item['content:encoded'].replaceAll(/(?<=<img.*src=")(.*)(?=".*\/>)/g, (match, p) => {
|
||||
if (p[0] === '/') {
|
||||
return cdn + feed.link + p;
|
||||
} else if (p.slice(0, 5) === 'http:') {
|
||||
@@ -37,7 +37,7 @@ module.exports = async (ctx) => {
|
||||
link: item.link,
|
||||
author: item.creator,
|
||||
};
|
||||
return Promise.resolve(article);
|
||||
return article;
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ module.exports = async (ctx) => {
|
||||
|
||||
const cache = await ctx.cache.get(link);
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
|
||||
const response2 = await got({
|
||||
@@ -39,7 +39,7 @@ module.exports = async (ctx) => {
|
||||
link,
|
||||
};
|
||||
ctx.cache.set(link, JSON.stringify(single));
|
||||
return Promise.resolve(single);
|
||||
return single;
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ module.exports = async (ctx) => {
|
||||
const link = $(item).attr('href');
|
||||
const cache = await ctx.cache.get(link);
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
const response2 = await got({
|
||||
method: 'get',
|
||||
@@ -41,7 +41,7 @@ module.exports = async (ctx) => {
|
||||
link,
|
||||
};
|
||||
ctx.cache.set(link, JSON.stringify(single));
|
||||
return Promise.resolve(single);
|
||||
return single;
|
||||
})
|
||||
);
|
||||
|
||||
@@ -50,16 +50,14 @@ module.exports = async (ctx) => {
|
||||
link: 'http://blur.com',
|
||||
description: $('description').text(),
|
||||
item: list.map((item, index) => {
|
||||
const Num = /[0-9]+/;
|
||||
const Num = /\d+/;
|
||||
let content = '';
|
||||
const videostyle = `width="640" height="360"`;
|
||||
const imgstyle = `style="max-width: 650px; height: auto; object-fit: contain; flex: 0 0 auto;"`;
|
||||
content += `Client:${articledata[index].client}<br>${articledata[index].describe}`;
|
||||
if (Num.test(articledata[index].mainvideo)) {
|
||||
content += `<iframe ${videostyle} src='https://player.vimeo.com/video/${articledata[index].mainvideo}' frameborder='0' webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe><br>`;
|
||||
} else {
|
||||
content += `<iframe ${videostyle} src='https://youtube.com/embed/${articledata[index].mainvideo}' frameborder='0' webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe><br>`;
|
||||
}
|
||||
content += Num.test(articledata[index].mainvideo)
|
||||
? `<iframe ${videostyle} src='https://player.vimeo.com/video/${articledata[index].mainvideo}' frameborder='0' webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe><br>`
|
||||
: `<iframe ${videostyle} src='https://youtube.com/embed/${articledata[index].mainvideo}' frameborder='0' webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe><br>`;
|
||||
if (articledata[index].images) {
|
||||
for (let p = 0; p < articledata[index].images.length; p++) {
|
||||
content += `<img ${imgstyle} src="${articledata[index].images[p].img}"><br>`;
|
||||
|
||||
@@ -6,7 +6,7 @@ const maxPages = 5;
|
||||
module.exports = async (ctx) => {
|
||||
const { subdomain } = ctx.params;
|
||||
if (!isValidHost(subdomain)) {
|
||||
throw Error('Invalid subdomain');
|
||||
throw new Error('Invalid subdomain');
|
||||
}
|
||||
const shopUrl = `https://${subdomain}.booth.pm`;
|
||||
|
||||
@@ -30,9 +30,7 @@ module.exports = async (ctx) => {
|
||||
break;
|
||||
}
|
||||
|
||||
for (let i = 0; i < pageItems.length; ++i) {
|
||||
const pageItem = pageItems[i];
|
||||
|
||||
for (const pageItem of pageItems) {
|
||||
// extract item name
|
||||
const itemName = $('h2.item-name > a', pageItem).text();
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ module.exports = async (ctx) => {
|
||||
return {
|
||||
link: item.attr('href'),
|
||||
title: item.find('h5').text(),
|
||||
pubDate: new Date(item.find('span').text().replace(/年|月/g, '-').replace(/日/, '')).toUTCString(),
|
||||
pubDate: new Date(item.find('span').text().replaceAll(/年|月/g, '-').replace(/日/, '')).toUTCString(),
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
@@ -37,7 +37,7 @@ module.exports = async (ctx) => {
|
||||
const pubDate = new Date($('dc\\:date').text()).toUTCString();
|
||||
const cache = await ctx.cache.get(address);
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
const itemPage = await got.get(address);
|
||||
const itemCapture = cheerio.load(itemPage.data);
|
||||
@@ -101,7 +101,7 @@ module.exports = async (ctx) => {
|
||||
pubDate,
|
||||
};
|
||||
ctx.cache.set(address, JSON.stringify(single));
|
||||
return Promise.resolve(single);
|
||||
return single;
|
||||
})
|
||||
);
|
||||
ctx.state.data = {
|
||||
|
||||
@@ -94,7 +94,7 @@ module.exports = async (ctx) => {
|
||||
pubDate: new Date(pageMeta.issueDate).toUTCString(),
|
||||
};
|
||||
ctx.cache.set(address, JSON.stringify(single));
|
||||
return Promise.resolve(single);
|
||||
return single;
|
||||
})
|
||||
);
|
||||
ctx.state.data = {
|
||||
|
||||
@@ -24,7 +24,7 @@ module.exports = async (ctx) => {
|
||||
|
||||
const cache = await ctx.cache.get(link);
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
|
||||
const description = await ProcessFeed(link);
|
||||
@@ -37,7 +37,7 @@ module.exports = async (ctx) => {
|
||||
};
|
||||
|
||||
ctx.cache.set(link, JSON.stringify(single));
|
||||
return Promise.resolve(single);
|
||||
return single;
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ module.exports = async (ctx) => {
|
||||
return {
|
||||
title: a.text(),
|
||||
link: a.attr('href'),
|
||||
pubDate: new Date(parseInt(a.attr('data-time'))).toUTCString(),
|
||||
pubDate: new Date(Number.parseInt(a.attr('data-time'))).toUTCString(),
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
@@ -20,7 +20,7 @@ module.exports = async (ctx) => {
|
||||
return {
|
||||
title: a.text(),
|
||||
link: a.attr('href'),
|
||||
pubDate: new Date(parseInt(a.attr('data-time'))).toUTCString(),
|
||||
pubDate: new Date(Number.parseInt(a.attr('data-time'))).toUTCString(),
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
@@ -35,7 +35,7 @@ module.exports = async (ctx) => {
|
||||
|
||||
item.author = content('.info h3').eq(0).text();
|
||||
item.description = content('.postBody').eq(0).html();
|
||||
item.pubDate = new Date(parseInt(content('.info .time').attr('data-timestamp')) * 1000).toUTCString();
|
||||
item.pubDate = new Date(Number.parseInt(content('.info .time').attr('data-timestamp')) * 1000).toUTCString();
|
||||
|
||||
return item;
|
||||
})
|
||||
|
||||
@@ -43,11 +43,11 @@ module.exports = async (ctx) => {
|
||||
'.recommender',
|
||||
'[class*="pb-f-ads-"]',
|
||||
];
|
||||
unwanted_element_selectors.forEach((selector) => {
|
||||
for (const selector of unwanted_element_selectors) {
|
||||
content.find(selector).each((i, e) => {
|
||||
$(e).remove();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
title: item.title.trim(),
|
||||
|
||||
@@ -10,7 +10,7 @@ module.exports = async (ctx) => {
|
||||
feed.items.map(async (item) => {
|
||||
const cache = await ctx.cache.get(item.link);
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
|
||||
const response = await got({
|
||||
@@ -25,7 +25,7 @@ module.exports = async (ctx) => {
|
||||
|
||||
// replace placeholer image url
|
||||
imgNode.each((index, element) => {
|
||||
if ($(element).attr('src') && $(element).attr('src').indexOf('none.gif') !== -1) {
|
||||
if ($(element).attr('src') && $(element).attr('src').includes('none.gif')) {
|
||||
$(element).attr('src', $(element).attr('zoomfile'));
|
||||
}
|
||||
|
||||
@@ -51,12 +51,12 @@ module.exports = async (ctx) => {
|
||||
author: item.author,
|
||||
};
|
||||
ctx.cache.set(item.link, JSON.stringify(single));
|
||||
return Promise.resolve(single);
|
||||
return single;
|
||||
})
|
||||
);
|
||||
|
||||
let title = feed.title.split('-');
|
||||
title = `${title[title.length - 1]} - Chiphell`;
|
||||
title = `${title.at(-1)} - Chiphell`;
|
||||
|
||||
ctx.state.data = {
|
||||
title,
|
||||
|
||||
@@ -19,7 +19,7 @@ function pick_versions(raw_html) {
|
||||
const href = $('a', col).attr('href');
|
||||
let version = '';
|
||||
if (href) {
|
||||
version = href.split('/').slice(-1)[0];
|
||||
version = href.split('/').at(-1);
|
||||
}
|
||||
software.version = version;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ module.exports = async (ctx) => {
|
||||
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: `https://dig.chouti.com/top/${hour}hr?_=${+new Date()}`,
|
||||
url: `https://dig.chouti.com/top/${hour}hr?_=${Date.now()}`,
|
||||
headers: {
|
||||
Referer: 'https://dig.chouti.com/',
|
||||
},
|
||||
|
||||
@@ -22,7 +22,7 @@ module.exports = async (ctx) => {
|
||||
return {
|
||||
title: item.text(),
|
||||
pubDate: new Date(item.prev().text()).toUTCString(),
|
||||
link: link.indexOf('http') < 0 ? `${rootUrl}${link}` : link,
|
||||
link: link.includes('http') ? link : `${rootUrl}${link}`,
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
@@ -9,8 +9,8 @@ const types = {
|
||||
};
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const type = ctx.params.type ? ctx.params.type : 'hot';
|
||||
const category = ctx.params.category ? ctx.params.category : '0';
|
||||
const type = ctx.params.type ?? 'hot';
|
||||
const category = ctx.params.category ?? '0';
|
||||
const category_name = category === '0' ? '全部' : category;
|
||||
|
||||
const url = `http://www.cnu.cc/discoveryPage/${type}-${encodeURIComponent(category)}`;
|
||||
@@ -28,7 +28,7 @@ module.exports = async (ctx) => {
|
||||
|
||||
const cache = await ctx.cache.get(link);
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
|
||||
const rssitem = {
|
||||
@@ -43,11 +43,11 @@ module.exports = async (ctx) => {
|
||||
rssitem.author = result.author;
|
||||
rssitem.description = result.description;
|
||||
rssitem.pubDate = result.pubDate;
|
||||
} catch (err) {
|
||||
return Promise.resolve('');
|
||||
} catch {
|
||||
return '';
|
||||
}
|
||||
ctx.cache.set(link, JSON.stringify(rssitem));
|
||||
return Promise.resolve(rssitem);
|
||||
return rssitem;
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ module.exports = async (ctx) => {
|
||||
|
||||
const cache = await ctx.cache.get(link);
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
|
||||
const rssitem = {
|
||||
@@ -30,17 +30,17 @@ module.exports = async (ctx) => {
|
||||
const response = await got.get(link);
|
||||
const result = utils.parseContent(response.data);
|
||||
if (!result.description) {
|
||||
return Promise.resolve('');
|
||||
return '';
|
||||
}
|
||||
|
||||
rssitem.author = result.author;
|
||||
rssitem.description = result.description;
|
||||
rssitem.pubDate = result.pubDate;
|
||||
} catch (err) {
|
||||
return Promise.resolve('');
|
||||
} catch {
|
||||
return '';
|
||||
}
|
||||
ctx.cache.set(link, JSON.stringify(rssitem));
|
||||
return Promise.resolve(rssitem);
|
||||
return rssitem;
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
@@ -10,10 +10,10 @@ const parseContent = (htmlString) => {
|
||||
const content = $('#work_body');
|
||||
|
||||
const imgs_json = JSON.parse($('#imgs_json').text());
|
||||
for (let k = 0; k < imgs_json.length; k++) {
|
||||
content.append(`<img src="${pic_base_url}${imgs_json[k].img}" />`);
|
||||
content.append(`<div class='img_description'>${imgs_json[k].content}</div>`);
|
||||
content.append(`<p>${imgs_json[k].text}</p>`);
|
||||
for (const element of imgs_json) {
|
||||
content.append(`<img src="${pic_base_url}${element.img}" />`);
|
||||
content.append(`<div class='img_description'>${element.content}</div>`);
|
||||
content.append(`<p>${element.text}</p>`);
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@@ -11,10 +11,8 @@ module.exports = async (ctx) => {
|
||||
const $listElement = $(this);
|
||||
const title = $listElement.find('span.release-number').text();
|
||||
if (title) {
|
||||
if (!includePreRelease) {
|
||||
if (title.includes('rc')) {
|
||||
return;
|
||||
}
|
||||
if (!includePreRelease && title.includes('rc')) {
|
||||
return;
|
||||
}
|
||||
items.push({
|
||||
title: $listElement.find('span.release-number').text(),
|
||||
|
||||
@@ -21,7 +21,7 @@ const config = {
|
||||
module.exports = async (ctx) => {
|
||||
const cfg = config[ctx.params.caty];
|
||||
if (!cfg) {
|
||||
throw Error('Bad category. See <a href="https://docs.rsshub.app/routes/finance#zhong-zheng-wang-zi-xun">docs</a>');
|
||||
throw new Error('Bad category. See <a href="https://docs.rsshub.app/routes/finance#zhong-zheng-wang-zi-xun">docs</a>');
|
||||
}
|
||||
|
||||
const currentUrl = url.resolve(rootUrl, cfg.link);
|
||||
|
||||
@@ -67,7 +67,7 @@ module.exports = async (ctx) => {
|
||||
|
||||
const cache = await ctx.cache.get(itemUrl);
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
@@ -81,13 +81,13 @@ module.exports = async (ctx) => {
|
||||
link: itemUrl,
|
||||
description: $('.contents')
|
||||
.html()
|
||||
.replace(/src="\//g, `src="${url.resolve(baseUrl, '.')}`)
|
||||
.replace(/href="\//g, `href="${url.resolve(baseUrl, '.')}`)
|
||||
.replaceAll('src="/', `src="${url.resolve(baseUrl, '.')}`)
|
||||
.replaceAll('href="/', `href="${url.resolve(baseUrl, '.')}`)
|
||||
.trim(),
|
||||
pubDate: dateList[index],
|
||||
};
|
||||
ctx.cache.set(itemUrl, JSON.stringify(single));
|
||||
return Promise.resolve(single);
|
||||
return single;
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ module.exports = async (ctx) => {
|
||||
feed.items.map(async (item) => {
|
||||
const cache = await ctx.cache.get(item.link);
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
|
||||
const description = await ProcessFeed(item.link);
|
||||
@@ -32,7 +32,7 @@ module.exports = async (ctx) => {
|
||||
author: item.author,
|
||||
};
|
||||
ctx.cache.set(item.link, JSON.stringify(single));
|
||||
return Promise.resolve(single);
|
||||
return single;
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ module.exports = async (ctx) => {
|
||||
return {
|
||||
title: name,
|
||||
author: '低端影视',
|
||||
description: `<img src="${poster}" style="max-width: 100%;" >${text ? text : ''}`,
|
||||
description: `<img src="${poster}" style="max-width: 100%;" >${text ?? ''}`,
|
||||
link: item.find('.post-box-title a').attr('href'),
|
||||
pubDate: time,
|
||||
guid: md5(name),
|
||||
|
||||
@@ -21,7 +21,7 @@ module.exports = async (ctx) => {
|
||||
description: data[key],
|
||||
link: `${currentUrl}/${date}`,
|
||||
title: data['post_title_' + date],
|
||||
pubDate: new Date(`${date.substr(0, 4)}-${date.substr(4, 2)}-${date.substr(6, 2)}`).toUTCString(),
|
||||
pubDate: new Date(`${date.slice(0, 4)}-${date.slice(4, 6)}-${date.slice(6, 8)}`).toUTCString(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,10 +20,10 @@ module.exports = async (ctx) => {
|
||||
const $ = cheerio.load(html);
|
||||
$('div.crayons-story__body').each(function () {
|
||||
const post = {
|
||||
author: $('.crayons-story__secondary', this).text().trim().replace(/\s\s+/g, ', '),
|
||||
author: $('.crayons-story__secondary', this).text().trim().replaceAll(/\s\s+/g, ', '),
|
||||
title: $('.crayons-story__title a', this).text().trim(),
|
||||
link: `https://dev.to${$('.crayons-story__title a', this).attr('href')}`,
|
||||
description: $('.crayons-story__tags', this).text().trim().replace(/\s\s+/g, ' '),
|
||||
description: $('.crayons-story__tags', this).text().trim().replaceAll(/\s\s+/g, ' '),
|
||||
pubDate: new Date($('.time-ago-indicator-initial-placeholder', this).attr('data-seconds') * 1000).toUTCString(),
|
||||
};
|
||||
|
||||
|
||||
@@ -37,14 +37,14 @@ module.exports = async (ctx) => {
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.resolve({
|
||||
return {
|
||||
title,
|
||||
description,
|
||||
pubDate: new Date(item.send_at * 1000).toUTCString(),
|
||||
link: olink,
|
||||
category,
|
||||
author: item.author.username,
|
||||
});
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
const got = require('@/utils/got');
|
||||
const sanitizeHtml = require('sanitize-html');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const keyword = ctx.params.keyword;
|
||||
@@ -19,7 +20,7 @@ module.exports = async (ctx) => {
|
||||
title: `数字尾巴 - 闲置 - ${keyword}`,
|
||||
link: url,
|
||||
item: list.map((item) => ({
|
||||
title: item.title.replace(/<.*?>/g, ''),
|
||||
title: sanitizeHtml(item.title, { allowedTags: [], allowedAttributes: {} }),
|
||||
author: item.author.username,
|
||||
description: `<p>价格: ¥${item.price}</p><p>地址: ${item.address}</p><p>${item.content}</p><img src="${item.cover}" style="max-width: 100%;"/>`,
|
||||
pubDate: new Date(item.created_at * 1000),
|
||||
|
||||
@@ -13,7 +13,7 @@ const type_names = {
|
||||
};
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const typeId = ctx.params.typeId ? ctx.params.typeId : '0';
|
||||
const typeId = ctx.params.typeId ?? '0';
|
||||
|
||||
const url = 'https://www.dgtle.com/sale';
|
||||
|
||||
@@ -25,7 +25,7 @@ module.exports = async (ctx) => {
|
||||
},
|
||||
});
|
||||
|
||||
const type_name = type_names[typeId] ? type_names[typeId] : typeId;
|
||||
const type_name = type_names[typeId] ?? typeId;
|
||||
const list = response.data.data.dataList;
|
||||
|
||||
ctx.state.data = {
|
||||
|
||||
@@ -34,9 +34,9 @@ module.exports = async (ctx) => {
|
||||
const habits = habitsRes.data;
|
||||
|
||||
const paramsList = [];
|
||||
habits.forEach((item) => {
|
||||
for (const item of habits) {
|
||||
paramsList.push(['habitIds', item.id]);
|
||||
});
|
||||
}
|
||||
const searchParams = new URLSearchParams(paramsList);
|
||||
|
||||
const habitCheckinsRes = await got.get({
|
||||
@@ -55,8 +55,9 @@ module.exports = async (ctx) => {
|
||||
let list = [];
|
||||
for (const habitId in checkins.checkins) {
|
||||
const info = habits.find((item) => item.id === habitId);
|
||||
list = list.concat(
|
||||
checkins.checkins[habitId]
|
||||
list = [
|
||||
...list,
|
||||
...checkins.checkins[habitId]
|
||||
.sort((a, b) => a.checkinStamp - b.checkinStamp)
|
||||
.filter((checkin) => checkin.value)
|
||||
.map((checkin, index) => {
|
||||
@@ -68,8 +69,8 @@ module.exports = async (ctx) => {
|
||||
link: `https://dida365.com/webapp/#q/all/habit/${checkin.habitId}`,
|
||||
guid: checkin.id,
|
||||
};
|
||||
})
|
||||
);
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
ctx.state.data = {
|
||||
@@ -78,6 +79,6 @@ module.exports = async (ctx) => {
|
||||
item: list,
|
||||
};
|
||||
} else {
|
||||
throw Error('Login required');
|
||||
throw new Error('Login required');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -45,7 +45,7 @@ module.exports = async (ctx) => {
|
||||
const cache = await ctx.cache.get(itemUrl);
|
||||
// 判断缓存
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
const res = await got.get(itemUrl);
|
||||
const $ = cheerio.load(res.data);
|
||||
|
||||
@@ -16,7 +16,7 @@ module.exports = async (ctx) => {
|
||||
const cache = await ctx.cache.get(itemUrl);
|
||||
// 判断缓存
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
const res = await got.get(itemUrl);
|
||||
const $ = cheerio.load(res.data);
|
||||
|
||||
@@ -29,7 +29,7 @@ module.exports = async (ctx) => {
|
||||
const cache = await ctx.cache.get(itemUrl);
|
||||
// 判断缓存
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
const res = await got.get(itemUrl);
|
||||
const $ = cheerio.load(res.data);
|
||||
|
||||
@@ -17,7 +17,7 @@ module.exports = async (ctx) => {
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const list = $('li a')
|
||||
.slice(0, ctx.query.limit ? parseInt(ctx.query.limit) : 15)
|
||||
.slice(0, ctx.query.limit ? Number.parseInt(ctx.query.limit) : 15)
|
||||
.map((_, item) => {
|
||||
item = $(item);
|
||||
|
||||
@@ -37,13 +37,13 @@ module.exports = async (ctx) => {
|
||||
});
|
||||
|
||||
const data = detailResponse.data
|
||||
.replace(/\[img\]https:\/\/www\.discuss\.com\.hk\/images\/common\/back\.gif\[\/img\]/g, '')
|
||||
.replace(/\[url=(.*?)\]/gm, '<a href="$1">')
|
||||
.replace(/\[(\w+)=(.*?)\]/gm, '<span style="$1: $2;">')
|
||||
.replace(/\[\/(color|size)\]/gm, '</span>')
|
||||
.replace(/\[\/url\]/gm, '</a>')
|
||||
.replace(/\[(\w+)\]/gm, '<$1>')
|
||||
.replace(/\[\/(\w+)\]/gm, '</$1>');
|
||||
.replaceAll('[img]https://www.discuss.com.hk/images/common/back.gif[/img]', '')
|
||||
.replaceAll(/\[url=(.*?)]/gm, '<a href="$1">')
|
||||
.replaceAll(/\[(\w+)=(.*?)]/gm, '<span style="$1: $2;">')
|
||||
.replaceAll(/\[\/(color|size)]/gm, '</span>')
|
||||
.replaceAll(/\[\/url]/gm, '</a>')
|
||||
.replaceAll(/\[(\w+)]/gm, '<$1>')
|
||||
.replaceAll(/\[\/(\w+)]/gm, '</$1>');
|
||||
|
||||
const content = cheerio.load(data);
|
||||
|
||||
|
||||
@@ -18,13 +18,13 @@ module.exports = async (ctx) => {
|
||||
const data = response.data.response;
|
||||
|
||||
const threadsObj = {};
|
||||
data.forEach((item) => {
|
||||
for (const item of data) {
|
||||
threadsObj[item.thread] = 1;
|
||||
});
|
||||
}
|
||||
let threadsQuery = '';
|
||||
Object.keys(threadsObj).forEach((item) => {
|
||||
for (const item of Object.keys(threadsObj)) {
|
||||
threadsQuery += `&thread=${item}`;
|
||||
});
|
||||
}
|
||||
|
||||
const responseThreads = await got({
|
||||
method: 'get',
|
||||
@@ -41,7 +41,7 @@ module.exports = async (ctx) => {
|
||||
link: `https://disqus.com/home/forums/${forum}`,
|
||||
description: `${forum} 的 disqus 评论`,
|
||||
item: data.map((item) => {
|
||||
const thread = threads.filter((i) => i.id === item.thread)[0];
|
||||
const thread = threads.find((i) => i.id === item.thread);
|
||||
return {
|
||||
title: `${item.author.name}: ${item.raw_message}`,
|
||||
description: `${item.author.name} 在《${thread.clean_title}》中发表评论: ${item.message}`,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const parser = require('@/utils/rss-parser');
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const dateParser = require('@/utils/dateParser');
|
||||
const dateParser = require('@/utils/date-parser');
|
||||
const domain = 'https://www.dongmanmanhua.cn';
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
@@ -23,7 +23,7 @@ module.exports = async (ctx) => {
|
||||
description: `<a href=${x.link} target="_blank">${x.title}</a>`,
|
||||
})),
|
||||
};
|
||||
} catch (error) {
|
||||
} catch {
|
||||
const { body } = await got.get(comicLink);
|
||||
const $ = cheerio.load(body);
|
||||
rss = {
|
||||
|
||||
@@ -29,11 +29,8 @@ module.exports = async (ctx) => {
|
||||
single.pubDate = value.pubDate;
|
||||
} else {
|
||||
const temp = await got(link);
|
||||
single.description = $(temp.data)
|
||||
.find('.subject-content')
|
||||
.html()
|
||||
.replace(/alt="\\"/g, '');
|
||||
single.pubDate = new Date($(temp.data).find('.subject-meta').text().trim().substr(0, 18)).toUTCString();
|
||||
single.description = $(temp.data).find('.subject-content').html().replaceAll('alt="\\"', '');
|
||||
single.pubDate = new Date($(temp.data).find('.subject-meta').text().trim().slice(0, 18)).toUTCString();
|
||||
|
||||
ctx.cache.set(key, {
|
||||
description: single.description,
|
||||
@@ -41,7 +38,7 @@ module.exports = async (ctx) => {
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.resolve(single);
|
||||
return single;
|
||||
})
|
||||
);
|
||||
ctx.state.data = { title: '多知网', link: 'http://www.duozhi.com/', description: '独立商业视角 新锐教育观察', item: result };
|
||||
|
||||
@@ -70,13 +70,9 @@ module.exports = async (ctx) => {
|
||||
const lang = ctx.params.lang || 'CN';
|
||||
const price = ctx.params.price || '1';
|
||||
|
||||
let currentUrl;
|
||||
|
||||
if (ctx.params.search) {
|
||||
currentUrl = `https://masterapi.edrawsoft.cn/api/publish?offset=0&count=30&order=PV&sort=DESC&search=${search}&lang=CN&price=1`;
|
||||
} else {
|
||||
currentUrl = `https://masterapi.edrawsoft.cn/api/publish${classId === '' ? '' : '2'}?offset=0&count=30${classId}&order=${order}&sort=${sort}&lang=${lang}&price=${price}`;
|
||||
}
|
||||
const currentUrl = ctx.params.search
|
||||
? `https://masterapi.edrawsoft.cn/api/publish?offset=0&count=30&order=PV&sort=DESC&search=${search}&lang=CN&price=1`
|
||||
: `https://masterapi.edrawsoft.cn/api/publish${classId === '' ? '' : '2'}?offset=0&count=30${classId}&order=${order}&sort=${sort}&lang=${lang}&price=${price}`;
|
||||
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
|
||||
@@ -31,11 +31,7 @@ module.exports = async (ctx) => {
|
||||
const rootUrl = 'http://www.eeo.com.cn';
|
||||
let currentUrl = rootUrl;
|
||||
|
||||
if (parseInt(column)) {
|
||||
currentUrl += legacyUrls[parseInt(column)];
|
||||
} else {
|
||||
currentUrl += `/${column}/${category}`;
|
||||
}
|
||||
currentUrl += Number.parseInt(column) ? legacyUrls[Number.parseInt(column)] : `/${column}/${category}`;
|
||||
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
|
||||
@@ -19,20 +19,15 @@ const config = {
|
||||
};
|
||||
|
||||
const get_date = (o) => {
|
||||
let date;
|
||||
const match = /(\d{4}\.\d+\.\d+)/.exec(o.text().trim());
|
||||
if (match) {
|
||||
date = match[1];
|
||||
} else {
|
||||
date = o.attr('datetime');
|
||||
}
|
||||
const date = match ? match[1] : o.attr('datetime');
|
||||
return new Date(date + ' GMT+9').toUTCString();
|
||||
};
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const cfg = config[ctx.params.type];
|
||||
if (!cfg) {
|
||||
throw Error('Bad type');
|
||||
throw new Error('Bad type');
|
||||
}
|
||||
|
||||
const response = await got({
|
||||
|
||||
@@ -15,9 +15,8 @@ module.exports = async (ctx) => {
|
||||
).data.result.category;
|
||||
|
||||
let category_name, description;
|
||||
for (let i = 0; i < categorys.length; i++) {
|
||||
const item = categorys[i];
|
||||
if (item.cateId === parseInt(id)) {
|
||||
for (const item of categorys) {
|
||||
if (item.cateId === Number.parseInt(id)) {
|
||||
category_name = item.cateName;
|
||||
description = item.cateDescription;
|
||||
break;
|
||||
@@ -43,7 +42,7 @@ module.exports = async (ctx) => {
|
||||
|
||||
const cache = await ctx.cache.get(itemUrl);
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
|
||||
const response = await got({
|
||||
@@ -64,7 +63,7 @@ module.exports = async (ctx) => {
|
||||
pubDate: new Date(date * 1000).toUTCString(),
|
||||
};
|
||||
ctx.cache.set(itemUrl, JSON.stringify(single));
|
||||
return Promise.resolve(single);
|
||||
return single;
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ module.exports = async (ctx) => {
|
||||
|
||||
const cache = await ctx.cache.get(link);
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
|
||||
const itemReponse = await got.get(link);
|
||||
|
||||
@@ -25,7 +25,7 @@ module.exports = async (ctx) => {
|
||||
|
||||
const cache = await ctx.cache.get(link);
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
|
||||
const itemReponse = await got.get(link);
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const parser = require('@/utils/rss-parser');
|
||||
const allowLang = ['chinese', 'cn', 'us', 'japanese', 'www'];
|
||||
const allowLang = new Set(['chinese', 'cn', 'us', 'japanese', 'www']);
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const lang = ctx.params.lang === 'us' ? 'www' : ctx.params.lang || 'cn';
|
||||
if (!allowLang.includes(lang)) {
|
||||
throw Error('Invalid lang');
|
||||
if (!allowLang.has(lang)) {
|
||||
throw new Error('Invalid lang');
|
||||
}
|
||||
const rssUrl = `https://${lang}.engadget.com/rss.xml`;
|
||||
const feed = await parser.parseURL(rssUrl);
|
||||
@@ -39,7 +39,7 @@ module.exports = async (ctx) => {
|
||||
feed.items.map(async (item) => {
|
||||
const cache = await ctx.cache.get(item.link);
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
return JSON.parse(cache);
|
||||
}
|
||||
|
||||
const response = await got.get(item.link);
|
||||
@@ -53,7 +53,7 @@ module.exports = async (ctx) => {
|
||||
author: item.author,
|
||||
};
|
||||
ctx.cache.set(item.link, JSON.stringify(single));
|
||||
return Promise.resolve(single);
|
||||
return single;
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ module.exports = async (ctx) => {
|
||||
list &&
|
||||
list.map((item) => {
|
||||
const title = ` TransactionHash: ${item.hash} `;
|
||||
const value = (parseFloat(item.value) / 10 ** 18).toFixed(8);
|
||||
const value = (Number.parseFloat(item.value) / 10 ** 18).toFixed(8);
|
||||
const description = `
|
||||
From: ${item.from} <br> To: ${item.to} <br> Value: ${value} <br> Block: ${item.blockNumber}`;
|
||||
const link = `https://etherscan.io/tx/${item.hash}`;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user