diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index ce07aa9cbc..90518bb33c 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -29,6 +29,8 @@ jobs: - run: pnpm i - name: Install oxlint to SARIF converter run: pnpm i -g oxlint-json-to-sarif + - name: Typecheck + run: pnpm typecheck - name: Lint run: pnpm exec oxlint --type-aware --config=.oxlintrc.ci.json --format=json | oxlint-json-to-sarif > oxlint-results.sarif diff --git a/.husky/pre-commit b/.husky/pre-commit index c27d8893a9..4fe5222fef 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1 +1,2 @@ lint-staged +pnpm typecheck diff --git a/.oxlintrc.json b/.oxlintrc.json index 5936fe34c6..43cd83ec49 100644 --- a/.oxlintrc.json +++ b/.oxlintrc.json @@ -641,7 +641,17 @@ // #region --- TypeScript --- "@typescript-eslint/array-type": ["error", { "default": "array-simple" }], - "@typescript-eslint/ban-ts-comment": "off", + "@typescript-eslint/ban-ts-comment": [ + "warn", + { + "ts-check": false, + "ts-expect-error": "allow-with-description", + "ts-ignore": "allow-with-description", + "ts-nocheck": "allow-with-description", + "minimumDescriptionLength": 3 + } + ], + "@typescript-eslint/consistent-indexed-object-style": "off", // stylistic "@typescript-eslint/consistent-type-definitions": "off", // stylistic "@typescript-eslint/dot-notation": "error", // type-aware diff --git a/lib/api/follow/config.test.ts b/lib/api/follow/config.test.ts index c8da4ffb18..e9279a3fa8 100644 --- a/lib/api/follow/config.test.ts +++ b/lib/api/follow/config.test.ts @@ -14,7 +14,7 @@ describe('api/follow/config', () => { json: (data: unknown) => data, }; - const result = handler(ctx as any) as Record; + const result = (handler as (c: typeof ctx) => unknown)(ctx) as Record; expect(result).toMatchObject({ ownerUserId: 'owner', diff --git a/lib/api/radar/rules/one.test.ts b/lib/api/radar/rules/one.test.ts index e5afe4abb1..37e008b8d5 100644 --- a/lib/api/radar/rules/one.test.ts +++ b/lib/api/radar/rules/one.test.ts @@ -1,4 +1,4 @@ -import type { Next } from 'hono'; +import type { Context, Next } from 'hono'; import { describe, expect, it, vi } from 'vitest'; import { handler } from '@/api/radar/rules/one'; @@ -14,7 +14,7 @@ describe('api/radar/rules/one', () => { json: vi.fn((value) => value), }; - const result = await handler(ctx as any, noopNext); + const result = await handler(ctx as unknown as Context, noopNext); expect(ctx.req.valid).toHaveBeenCalledWith('param'); expect(ctx.json).toHaveBeenCalledWith(undefined); diff --git a/lib/app-bootstrap.test.tsx b/lib/app-bootstrap.test.tsx index 980c9355ec..099c780d52 100644 --- a/lib/app-bootstrap.test.tsx +++ b/lib/app-bootstrap.test.tsx @@ -21,7 +21,7 @@ describe('app-bootstrap', () => { const before = new Set(process.listeners('uncaughtException')); await import('@/app-bootstrap'); const after = process.listeners('uncaughtException'); - const listener = after.find((fn) => !before.has(fn)); + const listener = after.find((fn) => !before.has(fn)) as ((error: Error) => void) | undefined; expect(listener).toBeDefined(); listener?.(new Error('boom')); diff --git a/lib/app.test.ts b/lib/app.test.ts index 935412324d..03ca942bc9 100644 --- a/lib/app.test.ts +++ b/lib/app.test.ts @@ -23,7 +23,7 @@ describe('request-rewriter', () => { await app.request('/test/httperror'); // headers - const headers: Headers = fetchSpy.mock.lastCall?.[0].headers; + const headers: Headers = (fetchSpy.mock.lastCall as unknown as [Request])?.[0].headers; expect(headers.get('user-agent')).toMatch(/Chrome/); }); }); diff --git a/lib/container.ts b/lib/container.ts index f19cd3a997..6d3ddd5ea8 100644 --- a/lib/container.ts +++ b/lib/container.ts @@ -2,7 +2,7 @@ // This Worker manages the RSSHub container lifecycle and proxies requests import { Container } from '@cloudflare/containers'; -import type { KVNamespace } from '@cloudflare/workers-types'; +import type { DurableObjectNamespace, KVNamespace } from '@cloudflare/workers-types'; const INSTANCE_COUNT = 20; @@ -13,7 +13,7 @@ export class RSSHubContainer extends Container { } interface Env { - RSSHUB_CONTAINER: DurableObjectNamespace; + RSSHUB_CONTAINER: DurableObjectNamespace; CONFIG: KVNamespace; } @@ -36,7 +36,7 @@ export default { // Randomly select an instance for load balancing const instanceIndex = Math.floor(Math.random() * INSTANCE_COUNT); - const container = env.RSSHUB_CONTAINER.getByName(`rsshub-${instanceIndex}`); + const container = env.RSSHUB_CONTAINER.getByName(`rsshub-${instanceIndex}`) as unknown as RSSHubContainer; // Start container with env vars and wait for port to be ready await container.startAndWaitForPorts({ diff --git a/lib/errors/index.test.ts b/lib/errors/index.test.ts index 9e148abec4..73c5dbb821 100644 --- a/lib/errors/index.test.ts +++ b/lib/errors/index.test.ts @@ -1,4 +1,5 @@ import { load } from 'cheerio'; +import type { Context } from 'hono'; import { afterEach, describe, expect, it, vi } from 'vitest'; import app from '@/app'; @@ -147,9 +148,9 @@ describe('error handler honeybadger', () => { header: vi.fn(), json: (payload: unknown) => payload, html: (payload: unknown) => payload, - }; + } as unknown as Context; - errorHandler(new Error('boom'), ctx as any); + errorHandler(new Error('boom'), ctx); expect(notify).toHaveBeenCalledWith(expect.any(Error), { context: { name: 'test' }, @@ -205,9 +206,9 @@ describe('error handler sentry', () => { header: vi.fn(), json: (payload: unknown) => payload, html: (payload: unknown) => payload, - }; + } as unknown as Context; - errorHandler(new Error('boom'), ctx as any); + errorHandler(new Error('boom'), ctx); expect(setTag).toHaveBeenCalledWith('name', 'test'); expect(captureException).toHaveBeenCalled(); diff --git a/lib/index.test.ts b/lib/index.test.ts index 5f610af975..930df7feee 100644 --- a/lib/index.test.ts +++ b/lib/index.test.ts @@ -1,6 +1,6 @@ import { afterEach, describe, expect, it, vi } from 'vitest'; -const serve = vi.fn(() => ({ close: vi.fn() })); +const serve = vi.fn<(...args: any[]) => any>(() => ({ close: vi.fn() })); const logger = { info: vi.fn(), warn: vi.fn(), diff --git a/lib/middleware/anti-hotlink.test.ts b/lib/middleware/anti-hotlink.test.ts index 2470361bc2..cbed73a098 100644 --- a/lib/middleware/anti-hotlink.test.ts +++ b/lib/middleware/anti-hotlink.test.ts @@ -1,3 +1,4 @@ +import type { Context } from 'hono'; import Parser from 'rss-parser'; import { afterAll, afterEach, beforeAll, describe, expect, it, vi } from 'vitest'; @@ -451,7 +452,7 @@ describe('anti-hotlink edge cases', () => { }, get: (key: string) => store.get(key), set: (key: string, value: unknown) => store.set(key, value), - }; + } as unknown as Context; }; beforeAll(() => { @@ -479,7 +480,7 @@ describe('anti-hotlink edge cases', () => { }; const ctx = createCtx({ image_hotlink_template: 'https://img.test/${href}' }, data); - await antiHotlink(ctx as any, async () => {}); + await antiHotlink(ctx, async () => {}); expect(data.image).toBe('http://invalid url'); expect(errorSpy).toHaveBeenCalled(); @@ -495,7 +496,7 @@ describe('anti-hotlink edge cases', () => { }; const ctx = createCtx({ multimedia_hotlink_template: 'https://media.test/${href}' }, data); - await antiHotlink(ctx as any, async () => {}); + await antiHotlink(ctx, async () => {}); expect(data.image).toBe('https://example.com/img.jpg'); }); diff --git a/lib/middleware/cache.test.ts b/lib/middleware/cache.test.ts index 0c8e7042f4..b83ad45870 100644 --- a/lib/middleware/cache.test.ts +++ b/lib/middleware/cache.test.ts @@ -1,3 +1,4 @@ +import type { Context } from 'hono'; import Parser from 'rss-parser'; import { afterAll, afterEach, describe, expect, it, vi } from 'vitest'; @@ -190,7 +191,7 @@ describe('cache', () => { }); describe('cache middleware error handling', () => { - const setSpy = vi.fn(() => null); + const setSpy = vi.fn<(...args: any[]) => null>(() => null); const getSpy = vi.fn(() => null); afterAll(() => { @@ -231,10 +232,10 @@ describe('cache middleware error handling', () => { header: vi.fn(), set: vi.fn(), get: vi.fn(), - }; + } as unknown as Context; await expect( - cacheMiddleware(ctx as any, () => { + cacheMiddleware(ctx, () => { throw new Error('boom'); }) ).rejects.toThrow('boom'); diff --git a/lib/middleware/parameter.test.ts b/lib/middleware/parameter.test.ts index ac038cb3dc..3d639fc6eb 100644 --- a/lib/middleware/parameter.test.ts +++ b/lib/middleware/parameter.test.ts @@ -1,3 +1,4 @@ +import type { Context } from 'hono'; import Parser from 'rss-parser'; import { afterAll, afterEach, beforeAll, describe, expect, it, vi } from 'vitest'; @@ -19,8 +20,8 @@ const runMiddleware = async (data: any, query: Record store.get(key), set: (key: string, value: unknown) => store.set(key, value), - }; - await middleware(ctx as any, async () => {}); + } as unknown as Context; + await middleware(ctx, async () => {}); return store.get('data') as any; }; diff --git a/lib/middleware/parameter.ts b/lib/middleware/parameter.ts index 5dbad3d65e..2058ad5b5a 100644 --- a/lib/middleware/parameter.ts +++ b/lib/middleware/parameter.ts @@ -201,7 +201,7 @@ const middleware: MiddlewareHandler = async (ctx, next) => { const title = item.title || ''; const description = item.description || title; const author = getAuthorString(item); - const category = item.category || []; + const category = (item.category as string[] | undefined) || []; const isFilter = regex instanceof RE2JS ? regex.matcher(title).find() || regex.matcher(description).find() || regex.matcher(author).find() || category.some((c) => regex.matcher(c).find()) @@ -217,7 +217,7 @@ const middleware: MiddlewareHandler = async (ctx, next) => { const title = item.title || ''; const description = item.description || title; const author = getAuthorString(item); - const category = item.category || []; + const category = (item.category as string[] | undefined) || []; let isFilter = true; if (ctx.req.query('filter_title')) { @@ -246,7 +246,7 @@ const middleware: MiddlewareHandler = async (ctx, next) => { const title = item.title; const description = item.description || title; const author = getAuthorString(item); - const category = item.category || []; + const category = (item.category as string[] | undefined) || []; let isFilter = true; if (ctx.req.query('filterout') || ctx.req.query('filterout_title')) { diff --git a/lib/middleware/template.test.ts b/lib/middleware/template.test.ts index 088cb91d84..0712ee7d75 100644 --- a/lib/middleware/template.test.ts +++ b/lib/middleware/template.test.ts @@ -1,3 +1,4 @@ +import type { Context } from 'hono'; import { describe, expect, it, vi } from 'vitest'; import { config } from '@/config'; @@ -19,16 +20,16 @@ const createCtx = (query: Record, data: any, extra: redirect: vi.fn((url: string, status: number) => ({ url, status })), header: vi.fn(), res: { headers: new Headers() }, - }; + } as unknown as Context & { json: ReturnType; html: ReturnType; render: ReturnType; body: ReturnType; redirect: ReturnType; header: ReturnType }; }; describe('template middleware', () => { it('returns debug json when requested', async () => { const originalDebug = config.debugInfo; - config.debugInfo = true; + config.debugInfo = 'true'; const ctx = createCtx({ format: 'debug.json' }, { item: [] }, { json: { ok: true } }); - const result = await template(ctx as any, async () => {}); + const result = await template(ctx, async () => {}); expect(result).toEqual({ ok: true }); expect(ctx.json).toHaveBeenCalled(); @@ -38,7 +39,7 @@ describe('template middleware', () => { it('returns api data without rendering', async () => { const ctx = createCtx({}, null, { apiData: { ok: true } }); - const result = await template(ctx as any, async () => {}); + const result = await template(ctx, async () => {}); expect(result).toEqual({ ok: true }); expect(ctx.json).toHaveBeenCalledWith({ ok: true }); @@ -46,10 +47,10 @@ describe('template middleware', () => { it('renders debug html snippet when requested', async () => { const originalDebug = config.debugInfo; - config.debugInfo = true; + config.debugInfo = 'true'; const ctx = createCtx({ format: '0.debug.html' }, { item: [{ description: 'Hello' }] }); - const result = await template(ctx as any, async () => {}); + const result = await template(ctx, async () => {}); expect(result).toBe('Hello'); expect(ctx.html).toHaveBeenCalled(); @@ -72,7 +73,7 @@ describe('template middleware', () => { ], }; const ctx = createCtx({ format: 'rss' }, data); - await template(ctx as any, async () => {}); + await template(ctx, async () => {}); expect(data.item[0].title).toBe('ABC...'); expect(data.item[0].author).toBe('Alice, Bob'); @@ -93,7 +94,7 @@ describe('template middleware', () => { ], }; const ctx = createCtx({ format: 'json' }, data); - await template(ctx as any, async () => {}); + await template(ctx, async () => {}); expect(data.item[0].pubDate).toBe(''); expect(data.item[0].updated).toBe(''); @@ -101,7 +102,7 @@ describe('template middleware', () => { it('returns redirect response when redirect is set', async () => { const ctx = createCtx({}, { item: [] }, { redirect: 'https://example.com' }); - const result = await template(ctx as any, async () => {}); + const result = await template(ctx, async () => {}); expect(result).toEqual({ url: 'https://example.com', status: 301 }); expect(ctx.redirect).toHaveBeenCalledWith('https://example.com', 301); @@ -118,7 +119,7 @@ describe('template middleware', () => { ], }; const ctx = createCtx({ format: 'rss3' }, data); - const result = await template(ctx as any, async () => {}); + const result = await template(ctx, async () => {}); expect(ctx.json).toHaveBeenCalled(); expect(result).toHaveProperty('data'); @@ -135,7 +136,7 @@ describe('template middleware', () => { ], }; const ctx = createCtx({ format: 'atom' }, data); - await template(ctx as any, async () => {}); + await template(ctx, async () => {}); expect(ctx.render).toHaveBeenCalled(); }); diff --git a/lib/middleware/trace.test.ts b/lib/middleware/trace.test.ts index 5113af92ea..9689da02dd 100644 --- a/lib/middleware/trace.test.ts +++ b/lib/middleware/trace.test.ts @@ -1,3 +1,4 @@ +import type { Context, Next } from 'hono'; import { describe, expect, it } from 'vitest'; import { config } from '@/config'; @@ -6,7 +7,7 @@ import trace from '@/middleware/trace'; describe('trace middleware', () => { it('skips tracing when debugInfo is disabled', async () => { const originalDebug = config.debugInfo; - config.debugInfo = false; + config.debugInfo = false as unknown as string; let called = false; const ctx = { @@ -14,12 +15,13 @@ describe('trace middleware', () => { method: 'GET', raw: new Request('http://localhost/test'), }, - }; - const next = () => { + } as unknown as Context; + const next: Next = () => { called = true; + return Promise.resolve(); }; - await trace(ctx as any, next); + await trace(ctx, next); expect(called).toBe(true); config.debugInfo = originalDebug; diff --git a/lib/pkg.test.ts b/lib/pkg.test.ts index f0e1c78851..5a1a48016b 100644 --- a/lib/pkg.test.ts +++ b/lib/pkg.test.ts @@ -1,5 +1,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import type { Route } from '@/types'; + describe('pkg', () => { beforeEach(() => { vi.resetModules(); @@ -104,7 +106,7 @@ describe('pkg', () => { ], allowEmpty: true, }), - }, + } as unknown as Route, { name: 'Custom Namespace', url: 'https://example.com', @@ -128,7 +130,7 @@ describe('pkg', () => { path: '/hello', name: 'Custom Response', handler: () => new Response('ok'), - }); + } as unknown as Route); const app = (await import('@/app')).default; const response = await app.request('/custom-response/hello'); diff --git a/lib/registry-dev.test.ts b/lib/registry-dev.test.ts index ec589f284a..e41c3514b4 100644 --- a/lib/registry-dev.test.ts +++ b/lib/registry-dev.test.ts @@ -88,7 +88,7 @@ afterAll(() => { const buildApp = () => { const namespaces: NamespacesType = {}; const dev = createDevRegistry({ routesDirectory, namespaces }); - const app = new Hono(); + const app = new Hono<{ Variables: { fromOuter: string; data: Record; apiData: Record } }>(); app.use(async (ctx, next) => { ctx.set('fromOuter', 'bridged'); await next(); diff --git a/lib/registry.test.ts b/lib/registry.test.ts index da75e19337..0e8b2535e3 100644 --- a/lib/registry.test.ts +++ b/lib/registry.test.ts @@ -64,6 +64,7 @@ describe('registry', () => { vi.stubEnv('DISABLE_NSFW', 'true'); const { namespaces } = await import('./registry'); + // @ts-ignore build artifact of pnpm build:routes const routesModule = await import('../assets/build/routes.json'); const rawNamespaces = (routesModule.default ?? routesModule) as Record }>; const nsfwNamespaces = Object.entries(rawNamespaces).filter(([, namespace]) => Object.values(namespace.routes ?? {}).some((route) => route.features?.nsfw)); @@ -165,7 +166,7 @@ const perDirectoryMock = (fakeDirectories: Record { - const app = new Hono(); + const app = new Hono<{ Variables: { data: Record; apiData: Record } }>(); app.use(async (ctx, next) => { const response = await next(); const apiData = ctx.get('apiData'); diff --git a/lib/registry.ts b/lib/registry.ts index d559b57ecd..7c5c01d93c 100644 --- a/lib/registry.ts +++ b/lib/registry.ts @@ -38,17 +38,19 @@ let namespaces: NamespacesType = {}; let devRegistry: DevRegistry | undefined; if (config.isPackage) { + // @ts-ignore build artifact of pnpm build:routes namespaces = (await import('../assets/build/routes.js')).default; } else { switch (process.env.NODE_ENV || process.env.VERCEL_ENV) { case 'production': + // @ts-ignore build artifact of pnpm build:routes namespaces = (await import('../assets/build/routes.js')).default; break; case 'test': - // @ts-expect-error + // @ts-expect-error TS2322 the JSON module's inferred literal type is narrower than NamespacesType namespaces = await import('../assets/build/routes.json'); if (namespaces.default) { - // @ts-ignore + // @ts-expect-error TS2322 the JSON module's default export does not satisfy NamespacesType namespaces = namespaces.default; } break; diff --git a/lib/routes/005/index.tsx b/lib/routes/005/index.tsx index 734edf37ca..4a3f743026 100644 --- a/lib/routes/005/index.tsx +++ b/lib/routes/005/index.tsx @@ -1,7 +1,7 @@ import { load } from 'cheerio'; import { renderToString } from 'hono/jsx/dom/server'; -import type { Route } from '@/types'; +import type { DataItem, Language, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -23,11 +23,11 @@ export const handler = async (ctx) => { let items = $('div.article-list ul li') .slice(0, limit) .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem & { link: string } => { + const $item = $(item); - const title = item.find('h3').text(); - const image = item.find('img').prop('src'); + const title = $item.find('h3').text(); + const image = $item.find('img').prop('src'); const description = renderToString( <> @@ -36,22 +36,22 @@ export const handler = async (ctx) => { {title} ) : null} - {item.find('div.p-row').text() ?
{item.find('div.p-row').text()}
: null} + {$item.find('div.p-row').text() ?
{$item.find('div.p-row').text()}
: null} ); return { title, description, - pubDate: parseDate(item.find('span.time').text()), - link: new URL(item.find('h3 a').prop('href'), rootUrl).href, + pubDate: parseDate($item.find('span.time').text()), + link: new URL($item.find('h3 a').prop('href')!, rootUrl).href, content: { html: description, - text: item.find('div.p-row').text(), + text: $item.find('div.p-row').text(), }, image, banner: image, - language, + language: language as Language, }; }); @@ -66,14 +66,14 @@ export const handler = async (ctx) => { const description = $$('div.articleContent').html(); item.title = title; - item.description = description; + item.description = description ?? ''; item.pubDate = timezone(parseDate($$('.time').text()), 8); item.category = $$('meta[name="keywords"]').prop('content').split(/,/); item.content = { - html: description, + html: description ?? '', text: $$('div.articleContent').text(), }; - item.language = language; + item.language = language as Language; return item; }) @@ -91,7 +91,7 @@ export const handler = async (ctx) => { allowEmpty: true, image, author: title.split(/,/).pop(), - language, + language: language as Language, }; }; diff --git a/lib/routes/0818tuan/index.ts b/lib/routes/0818tuan/index.ts index 6605b42ef1..347f81aee0 100644 --- a/lib/routes/0818tuan/index.ts +++ b/lib/routes/0818tuan/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -37,18 +37,18 @@ async function handler(ctx) { const list = $(listId === '3' ? '.col-xs-12 .thumbnail > a' : '.col-md-8 .list-group > a') .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); return { - title: item.attr('title'), - link: item.attr('href').startsWith('http') ? item.attr('href') : `${baseUrl}${item.attr('href')}`, + title: $item.attr('title')!, + link: $item.attr('href')!.startsWith('http') ? $item.attr('href') : `${baseUrl}${$item.attr('href')}`, }; }) - .filter((i) => !i.link.includes('m.0818tuan.com/tb1111.php') && !i.link.includes('www.0818tuan.com/pdd/zudui.php')); + .filter((i) => !i.link!.includes('m.0818tuan.com/tb1111.php') && !i.link!.includes('www.0818tuan.com/pdd/zudui.php')); const items = await Promise.all( list.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const { data: response } = await got(item.link); const $ = load(response); diff --git a/lib/routes/0x80/index.ts b/lib/routes/0x80/index.ts index 13463db233..f4069561d3 100644 --- a/lib/routes/0x80/index.ts +++ b/lib/routes/0x80/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -37,11 +37,11 @@ async function handler() { const list = alist .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem & { link: string } => { + const $item = $(item); - const link = item.attr('href') || ''; - const title = item.text(); + const link = $item.attr('href') || ''; + const title = $item.text(); const pubDate = extractDateFromURL(link); return { diff --git a/lib/routes/0xxx/index.ts b/lib/routes/0xxx/index.ts index bfe02481d7..cf469492f7 100644 --- a/lib/routes/0xxx/index.ts +++ b/lib/routes/0xxx/index.ts @@ -3,7 +3,7 @@ import { load } from 'cheerio'; import type { Element } from 'domhandler'; import type { Context } from 'hono'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -25,7 +25,7 @@ export const handler = async (ctx: Context): Promise => { let items: DataItem[] = $('table#home-table tr:not(.gore)') .slice(0, limit) .toArray() - .map((el): Element => { + .map((el) => { const $el: Cheerio = $(el); const $categoryEl: Cheerio = $el.find('td.category'); @@ -44,11 +44,11 @@ export const handler = async (ctx: Context): Promise => { }, ] : undefined, - category: $categoryEl.html(), - catalogue: $catalogueEl.html(), + category: $categoryEl.html() ?? undefined, + catalogue: $catalogueEl.html() ?? undefined, title, size: $el.find('td.size').text(), - date: $dateEl.html(), + date: $dateEl.html() ?? undefined, }); const pubDateStr: string | undefined = $dateEl.text(); const linkUrl: string | undefined = $el.find('td.title a').attr('href'); @@ -68,7 +68,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: upDatedStr ? parseDate(upDatedStr, 'DD.MM.YYYY') : undefined, - language, + language: language as Language, }; return processedItem; @@ -81,7 +81,7 @@ export const handler = async (ctx: Context): Promise => { } return cache.tryGet(item.link, async (): Promise => { - const detailResponse = await ofetch(item.link); + const detailResponse = await ofetch(item.link!); const $$: CheerioAPI = load(detailResponse); const description: string | undefined = @@ -117,7 +117,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image: $('div.logo img').attr('src') ? new URL($('div.logo img').attr('src') as string, baseUrl).href : undefined, author: $('meta[property="og:site_name"]').attr('content'), - language, + language: language as Language, id: targetUrl, }; }; @@ -146,7 +146,7 @@ To subscribe to [Movie HD 1080p](https://0xxx.ws?category=Movie-HD-1080p), where supportBT: false, supportPodcast: false, supportScihub: false, - nfsw: true, + nsfw: true, }, radar: [ { diff --git a/lib/routes/10000link/info.ts b/lib/routes/10000link/info.ts index cbf4e69b72..9297c039e5 100644 --- a/lib/routes/10000link/info.ts +++ b/lib/routes/10000link/info.ts @@ -3,7 +3,7 @@ import { load } from 'cheerio'; import type { Element } from 'domhandler'; import type { Context } from 'hono'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -25,7 +25,7 @@ export const handler = async (ctx: Context): Promise => { let items: DataItem[] = $('ul.l_newshot li dl.lhotnew2') .slice(0, limit) .toArray() - .map((el): Element => { + .map((el) => { const $el: Cheerio = $(el); const $aEl: Cheerio = $el.find('dd h1 a'); @@ -55,7 +55,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: upDatedStr ? parseRelativeDate(upDatedStr) : undefined, - language, + language: language as Language, }; return processedItem; @@ -69,14 +69,14 @@ export const handler = async (ctx: Context): Promise => { } return cache.tryGet(item.link, async (): Promise => { - const detailResponse = await ofetch(item.link); + const detailResponse = await ofetch(item.link!); const $$: CheerioAPI = load(detailResponse); const title: string = $$('div.entity_title h1 a').text(); const image: string | undefined = $$('div.entity_thumb img.img-responsive').attr('src'); const description: string | undefined = renderDescription({ - description: $$('div.entity_content').html(), + description: $$('div.entity_content').html() ?? undefined, }); const pubDateStr: string | undefined = detailResponse.match(/var\stime\s=\s"(.*?)";/)?.[1]; const categoryEls: Element[] = $$('div.entity_tag span a').toArray(); @@ -95,7 +95,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: upDatedStr ? parseDate(upDatedStr) : item.updated, - language, + language: language as Language, }; return { @@ -118,7 +118,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image: $('a.navbar-brand img').attr('src') ? new URL($('a.navbar-brand img').attr('src') as string, baseUrl).href : undefined, author, - language, + language: language as Language, id: $('meta[property="og:url"]').attr('content'), }; }; diff --git a/lib/routes/10jqka/realtimenews.ts b/lib/routes/10jqka/realtimenews.ts index 6b8742133a..f230a71f0a 100644 --- a/lib/routes/10jqka/realtimenews.ts +++ b/lib/routes/10jqka/realtimenews.ts @@ -1,7 +1,7 @@ import { load } from 'cheerio'; import iconv from 'iconv-lite'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -51,7 +51,7 @@ export const handler = async (ctx) => { image, banner: item.picUrl, updated: parseDate(item.rtime, 'X'), - language, + language: language as Language, }; }) ?? []; @@ -66,7 +66,7 @@ export const handler = async (ctx) => { allowEmpty: true, image, author: $('meta[property="og:site_name"]').prop('content'), - language, + language: language as Language, }; }; diff --git a/lib/routes/121/weather-live.tsx b/lib/routes/121/weather-live.tsx index bc7b70de85..8c464607db 100644 --- a/lib/routes/121/weather-live.tsx +++ b/lib/routes/121/weather-live.tsx @@ -3,7 +3,7 @@ import { load } from 'cheerio'; import type { Context } from 'hono'; import { renderToString } from 'hono/jsx/dom/server'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import ofetch from '@/utils/ofetch'; import { parseDate } from '@/utils/parse-date'; @@ -70,7 +70,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: updated ? parseDate(updated) : undefined, - language, + language: language as Language, }; return processedItem; @@ -86,7 +86,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image: $('img').first().attr('src') ? new URL($('img').first().attr('src') as string, baseUrl).href : undefined, author: $('div#webnameDiv').text(), - language, + language: language as Language, id: targetUrl, }; }; diff --git a/lib/routes/12306/zxdt.ts b/lib/routes/12306/zxdt.ts index eebd0af520..5f66d442f5 100644 --- a/lib/routes/12306/zxdt.ts +++ b/lib/routes/12306/zxdt.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -42,9 +42,9 @@ async function handler(ctx) { const list = $('#newList > ul > li') .toArray() - .map((item) => ({ + .map((item): DataItem & { link: string } => ({ title: $(item).find('a').text(), - link: new URL($(item).find('a').attr('href'), link).href, + link: new URL($(item).find('a').attr('href')!, link).href, pubDate: parseDate($(item).find('span').text().slice(1, -1)), })); diff --git a/lib/routes/141jav/index.tsx b/lib/routes/141jav/index.tsx index 87517a609f..10f7beff55 100644 --- a/lib/routes/141jav/index.tsx +++ b/lib/routes/141jav/index.tsx @@ -68,29 +68,29 @@ async function handler(ctx) { const items = $('.columns') .toArray() .map((item) => { - item = $(item); + const $item = $(item); - const id = item.find('.title a').text(); - const size = item.find('.title span').text(); - const pubDate = item.find('.subtitle a').attr('href').split('/date/').pop(); - const description = item.find('.has-text-grey-dark').text(); - const actresses = item + const id = $item.find('.title a').text(); + const size = $item.find('.title span').text(); + const pubDate = $item.find('.subtitle a').attr('href')!.split('/date/').pop(); + const description = $item.find('.has-text-grey-dark').text(); + const actresses = $item .find('.panel-block') .toArray() .map((a) => $(a).text().trim()); - const tags = item + const tags = $item .find('.tag') .toArray() .map((t) => $(t).text().trim()); - const magnet = item.find('a[title="Magnet torrent"]').attr('href'); - const link = item.find('a[title="Download .torrent"]').attr('href'); - const image = item.find('.image').attr('src'); + const magnet = $item.find('a[title="Magnet torrent"]').attr('href'); + const link = $item.find('a[title="Download .torrent"]').attr('href'); + const image = $item.find('.image').attr('src'); return { title: `${id} ${size}`, - pubDate: parseDate(pubDate, 'YYYY/MM/DD'), - link: new URL(item.find('a').first().attr('href'), rootUrl).href, - description: renderToString(), + pubDate: parseDate(pubDate!, 'YYYY/MM/DD'), + link: new URL($item.find('a').first().attr('href')!, rootUrl).href, + description: renderToString(), author: actresses.join(', '), category: [...tags, ...actresses], enclosure_type: 'application/x-bittorrent', diff --git a/lib/routes/141ppv/index.tsx b/lib/routes/141ppv/index.tsx index 05172e45a8..4a9e427300 100644 --- a/lib/routes/141ppv/index.tsx +++ b/lib/routes/141ppv/index.tsx @@ -68,31 +68,31 @@ async function handler(ctx) { const items = $('.columns') .toArray() .map((item) => { - item = $(item); + const $item = $(item); - const id = item.find('.title a').text(); - const size = item.find('.title span').text(); - const pubDate = item.find('.subtitle a').attr('href').split('/date/').pop(); - const description = item.find('.has-text-grey-dark').text(); - const actresses = item + const id = $item.find('.title a').text(); + const size = $item.find('.title span').text(); + const pubDate = $item.find('.subtitle a').attr('href')!.split('/date/').pop(); + const description = $item.find('.has-text-grey-dark').text(); + const actresses = $item .find('.panel-block') .toArray() .map((a) => $(a).text().trim()); - const tags = item + const tags = $item .find('.tag') .toArray() .map((t) => $(t).text().trim()); - const magnet = item.find('a[title="Magnet torrent"]').attr('href'); - const link = item.find('a[title="Download .torrent"]').attr('href'); - const onErrorAttr = item.find('.image').attr('onerror'); + const magnet = $item.find('a[title="Magnet torrent"]').attr('href'); + const link = $item.find('a[title="Download .torrent"]').attr('href'); + const onErrorAttr = $item.find('.image').attr('onerror'); const backupImageRegex = /this\.src='(.*?)'/; - const match = backupImageRegex.exec(onErrorAttr); - const image = match ? match[1] : item.find('.image').attr('src'); + const match = backupImageRegex.exec(onErrorAttr!); + const image = match ? match[1] : $item.find('.image').attr('src'); return { title: `${id} ${size}`, - pubDate: parseDate(pubDate, 'YYYY/MM/DD'), - link: new URL(item.find('a').first().attr('href'), rootUrl).href, + pubDate: parseDate(pubDate!, 'YYYY/MM/DD'), + link: new URL($item.find('a').first().attr('href')!, rootUrl).href, description: renderToString( <> {image ? : null} diff --git a/lib/routes/163/dy2.ts b/lib/routes/163/dy2.ts index 06ff453d91..cfd448129d 100644 --- a/lib/routes/163/dy2.ts +++ b/lib/routes/163/dy2.ts @@ -38,12 +38,12 @@ async function handler(ctx) { .slice(0, limit) .toArray() .map((item) => { - item = $(item); - const itemImg = item.find('a.img img'); + const $item = $(item); + const itemImg = $item.find('a.img img'); return { - title: item.find('h4 a').text(), - link: item.find('a').first().attr('href'), - pubDate: timezone(parseDate(item.find('.time').text()), 8), + title: $item.find('h4 a').text(), + link: $item.find('a').first().attr('href'), + pubDate: timezone(parseDate($item.find('.time').text()), 8), imgsrc: itemImg.attr('src') ?? itemImg.attr('_src'), }; }); diff --git a/lib/routes/163/music/djradio.tsx b/lib/routes/163/music/djradio.tsx index 18d117a524..e97e96a120 100644 --- a/lib/routes/163/music/djradio.tsx +++ b/lib/routes/163/music/djradio.tsx @@ -42,7 +42,7 @@ const renderDescription = (pg, description, itunes_duration, info) => {info ? (
- +

时长: {itunes_duration}

查看节目 diff --git a/lib/routes/163/news/rank.ts b/lib/routes/163/news/rank.ts index 8cd03a5bf5..040dfc900a 100644 --- a/lib/routes/163/news/rank.ts +++ b/lib/routes/163/news/rank.ts @@ -2,7 +2,7 @@ import { load } from 'cheerio'; import iconv from 'iconv-lite'; import InvalidParameterError from '@/errors/types/invalid-parameter'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -140,24 +140,25 @@ async function handler(ctx) { .eq(timeRange[time].index + (category === 'whole' ? (type === 'click' ? -1 : 2) : type === 'click' ? 0 : 2)) .find('table tbody tr td a') .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); return { - link: item.attr('href'), + link: $item.attr('href'), + title: '', }; }); const items = await Promise.all( list.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { try { let link; if (['auto', 'house', 'travel'].includes(category)) { - const category = item.link.split('.163.com', 1)[0].split('//').pop().split('.').pop(); - link = `https://3g.163.com/${category}/article/${item.link.split('/').pop()}`; + const category = item.link!.split('.163.com', 1)[0].split('//').pop()!.split('.').pop(); + link = `https://3g.163.com/${category}/article/${item.link!.split('/').pop()}`; } else { - const pathname = new URL(item.link).pathname; + const pathname = new URL(item.link!).pathname; link = `https://3g.163.com${pathname}`; } @@ -175,8 +176,8 @@ async function handler(ctx) { elem.attribs.src = elem.attribs['data-src'] ?? elem.attribs.src; }); - item.title = content('meta[property="og:title"]').attr('content').replace('_手机网易网', ''); - item.pubDate = parseDate(content('meta[property="og:release_date"]').attr('content')); + item.title = content('meta[property="og:title"]').attr('content')!.replace('_手机网易网', ''); + item.pubDate = parseDate(content('meta[property="og:release_date"]').attr('content')!); item.description = content('.article-body').html(); } catch { return ''; @@ -190,6 +191,6 @@ async function handler(ctx) { return { title: `网易新闻${timeRange[time].title}${type === 'click' ? '点击' : '跟帖'}榜 - ${cfg.title}`, link: currentUrl, - item: items.filter(Boolean), + item: items.filter(Boolean) as DataItem[], }; } diff --git a/lib/routes/163/open/vip.tsx b/lib/routes/163/open/vip.tsx index 82784e98fb..c361976a0f 100644 --- a/lib/routes/163/open/vip.tsx +++ b/lib/routes/163/open/vip.tsx @@ -65,10 +65,10 @@ async function handler() { const initialState = JSON.parse( $('script') .text() - .match(/window\.__INITIAL_STATE__=(.*);\(function\(\)\{var/)[1] + .match(/window\.__INITIAL_STATE__=(.*);\(function\(\)\{var/)![1] ); - const list = Object.values(initialState.courseindex.myModules).flatMap((mod) => + const list = Object.values>(initialState.courseindex.myModules).flatMap((mod) => mod.contents.map((item) => ({ title: `${item.title} - ${item.subtitle}`, author: item.authorName, diff --git a/lib/routes/163/renjian.ts b/lib/routes/163/renjian.ts index d3d066ac67..c0a214b5b5 100644 --- a/lib/routes/163/renjian.ts +++ b/lib/routes/163/renjian.ts @@ -61,8 +61,8 @@ async function handler(ctx) { if (urls) { items = urls.slice(0, ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit')) : 50).map((item) => ({ - link: item.match(/url:"(.*)",/)[1], - })); + link: item.match(/url:"(.*)",/)![1], + })) as DataItem[]; } else { const $ = load(data); @@ -70,16 +70,16 @@ async function handler(ctx) { .slice(0, ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit')) : 50) .toArray() .map((_, item) => { - item = $(item); + const $item = $(item as any); return { - link: item.attr('href'), + link: $item.attr('href'), }; - }); + }) as DataItem[]; } items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const detailResponse = await got({ method: 'get', url: item.link, @@ -89,7 +89,7 @@ async function handler(ctx) { item.title = content('h1').text(); item.author = content('script') .text() - .match(/renjian_author = '(.*)'/)[1]; + .match(/renjian_author = '(.*)'/)![1]; item.description = content('#endText').html() ?? content('#content').html(); item.pubDate = timezone(parseDate(content('.pub_time').text() ?? content('.post_info').text().split('来源:', 1)[0].trim()), 8); diff --git a/lib/routes/163/utils.tsx b/lib/routes/163/utils.tsx index 2c2f109a8f..aa995215ff 100644 --- a/lib/routes/163/utils.tsx +++ b/lib/routes/163/utils.tsx @@ -32,7 +32,7 @@ const parseDyArticle = (item) => } const url = new URL(i.attribs.src); if (url.host === 'nimg.ws.126.net') { - i.attribs.src = url.searchParams.get('url'); + i.attribs.src = url.searchParams.get('url') ?? ''; } }); diff --git a/lib/routes/18comic/album.ts b/lib/routes/18comic/album.ts index c7a5f9a0da..4f50298873 100644 --- a/lib/routes/18comic/album.ts +++ b/lib/routes/18comic/album.ts @@ -1,4 +1,4 @@ -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import { renderDescription } from './templates/description'; @@ -70,7 +70,7 @@ async function handler(ctx) { cache.tryGet(`18comic:album:${item.id}`, async () => { const chapterApiUrl = `${getApiUrl()}/chapter?id=${item.id}`; const chapterResult = await processApiItems(chapterApiUrl); - const result = {}; + const result: DataItem = { title: '' }; const chapterNum = index + 1; result.title = `第${chapterNum}話 ${item.name === '' ? chapterNum : item.name}`; result.link = `${rootUrl}/photo/${item.id}`; diff --git a/lib/routes/18comic/blogs.ts b/lib/routes/18comic/blogs.ts index 65399a95c3..d3aafe958e 100644 --- a/lib/routes/18comic/blogs.ts +++ b/lib/routes/18comic/blogs.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -53,13 +53,13 @@ async function handler(ctx) { let items = $('.title') .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem & { guid: string } => { + const $item = $(item); return { - title: item.text(), - link: `${rootUrl}${item.parent().attr('href')}`, - guid: `https://18comic.org${item.parent().attr('href')}`, + title: $item.text(), + link: `${rootUrl}${$item.parent().attr('href')}`, + guid: `https://18comic.org${$item.parent().attr('href')}`, }; }); diff --git a/lib/routes/18comic/search.ts b/lib/routes/18comic/search.ts index 3b9a81c78b..2ed8b8bd12 100644 --- a/lib/routes/18comic/search.ts +++ b/lib/routes/18comic/search.ts @@ -1,4 +1,4 @@ -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import { parseDate } from '@/utils/parse-date'; @@ -67,11 +67,17 @@ async function handler(ctx) { const results = await Promise.all( filteredItemsByCategory.map((item) => cache.tryGet(`18comic:search:${item.id}`, async () => { - const result = { title: item.name, link: `${rootUrl}/album/${item.id}`, guid: `18comic:/album/${item.id}`, updated: parseDate(item.update_at) }; + const result: DataItem = { + title: item.name, + link: `${rootUrl}/album/${item.id}`, + guid: `18comic:/album/${item.id}`, + updated: parseDate(item.update_at), + }; const apiUrl = `${getApiUrl()}/album?id=${item.id}`; const apiResult = await processApiItems(apiUrl); result.pubDate = new Date(apiResult.addtime * 1000); - result.category = apiResult.tags.map((tag) => tag); + const tags = apiResult.tags.map((tag) => tag); + result.category = tags; result.author = apiResult.author.map((a) => a).join(', '); result.description = renderDescription({ introduction: apiResult.description, @@ -83,7 +89,7 @@ async function handler(ctx) { // `https://cdn-msp3.${domain}/media/photos/${item.id}/00003.webp`, ], cover: `https://cdn-msp3.${domain}/media/albums/${item.id}_3x4.jpg`, - category: result.category, + category: tags, }); return result; }) diff --git a/lib/routes/18comic/utils.ts b/lib/routes/18comic/utils.ts index a210ab843d..ae62a2b26e 100644 --- a/lib/routes/18comic/utils.ts +++ b/lib/routes/18comic/utils.ts @@ -3,6 +3,7 @@ import CryptoJS from 'crypto-js'; import { config } from '@/config'; import ConfigNotFoundError from '@/errors/types/config-not-found'; +import type { DataItem } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import md5 from '@/utils/md5'; @@ -99,13 +100,13 @@ const ProcessItems = async (ctx, currentUrl, rootUrl) => { let items = $('.video-title') .slice(0, ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit')) : 20) .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem & { guid: string } => { + const $item = $(item); return { - title: item.text().trim(), - link: `${rootUrl}${item.prev().find('a').attr('href')}`, - guid: `18comic:${item.prev().find('a').attr('href')}`, + title: $item.text().trim(), + link: `${rootUrl}${$item.prev().find('a').attr('href')}`, + guid: `18comic:${$item.prev().find('a').attr('href')}`, }; }); @@ -116,8 +117,8 @@ const ProcessItems = async (ctx, currentUrl, rootUrl) => { const content = load(detailResponse.data); - item.pubDate = parseDate(content('div[itemprop="datePublished"]').first().attr('content')); - item.updated = parseDate(content('div[itemprop="datePublished"]').last().attr('content')); + item.pubDate = parseDate(content('div[itemprop="datePublished"]').first().attr('content')!); + item.updated = parseDate(content('div[itemprop="datePublished"]').last().attr('content')!); item.category = content('span[data-type="tags"]') .first() .find('a') @@ -133,7 +134,7 @@ const ProcessItems = async (ctx, currentUrl, rootUrl) => { introduction: content('#intro-block .p-t-5').text(), images: content('.img_zoom_img img') .toArray() - .map((image) => content(image).attr('data-original')), + .map((image) => content(image).attr('data-original')!), cover: content('.thumb-overlay img').first().attr('src'), category: item.category, }); diff --git a/lib/routes/199it/index.tsx b/lib/routes/199it/index.tsx index b1d7ac29be..777a918657 100644 --- a/lib/routes/199it/index.tsx +++ b/lib/routes/199it/index.tsx @@ -4,7 +4,7 @@ import type { Element } from 'domhandler'; import type { Context } from 'hono'; import { renderToString } from 'hono/jsx/dom/server'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -24,7 +24,7 @@ export const handler = async (ctx: Context): Promise => { let items: DataItem[] = $('article.newsplus') .slice(0, limit) .toArray() - .map((el): Element => { + .map((el) => { const $el: Cheerio = $(el); const title: string = $el.find('h2.entry-title').text(); @@ -43,7 +43,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: upDatedStr ? parseDate(upDatedStr) : undefined, - language, + language: language as Language, }; return processedItem; @@ -57,7 +57,7 @@ export const handler = async (ctx: Context): Promise => { } return cache.tryGet(item.link, async (): Promise => { - const detailResponse = await ofetch(item.link); + const detailResponse = await ofetch(item.link!); const $$: CheerioAPI = load(detailResponse); $$('div.entry-content img.alignnone').each((_, el) => { @@ -85,7 +85,7 @@ export const handler = async (ctx: Context): Promise => { pubDate: pubDateStr ? parseDate(pubDateStr) : item.pubDate, category: categories, updated: upDatedStr ? parseDate(upDatedStr) : item.updated, - language, + language: language as Language, }; const extraLinkEls: Element[] = $$('ul.related_post li a').toArray(); @@ -112,7 +112,7 @@ export const handler = async (ctx: Context): Promise => { $$('ul.related_post').parent().remove(); - const description: string | undefined = $$('div.entry-content').html(); + const description: string | undefined = $$('div.entry-content').html() ?? undefined; processedItem = { ...processedItem, @@ -142,7 +142,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image: $('h3.site-title img').attr('src'), author: title.split(/-/).pop()?.trim(), - language, + language: language as Language, id: targetUrl, }; }; diff --git a/lib/routes/19lou/index.ts b/lib/routes/19lou/index.ts index 8cf8cba12d..6cd4d44069 100644 --- a/lib/routes/19lou/index.ts +++ b/lib/routes/19lou/index.ts @@ -2,7 +2,7 @@ import { load } from 'cheerio'; import iconv from 'iconv-lite'; import InvalidParameterError from '@/errors/types/invalid-parameter'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -10,12 +10,12 @@ import timezone from '@/utils/timezone'; import { isValidHost } from '@/utils/valid-host'; const setCookie = function (cookieName, cookieValue, seconds, path, domain, secure?) { - let expires = null; + let expires: Date | null = null; if (seconds !== -1) { expires = new Date(); expires.setTime(expires.getTime() + seconds); } - return [encodeURI(cookieName), '=', encodeURI(cookieValue), expires ? '; expires=' + expires.toGMTString() : '', path ? '; path=' + path : '/', domain ? '; domain=' + domain : '', secure ? '; secure' : ''].join(''); + return [encodeURI(cookieName), '=', encodeURI(cookieValue), expires ? '; expires=' + expires.toUTCString() : '', path ? '; path=' + path : '/', domain ? '; domain=' + domain : '', secure ? '; secure' : ''].join(''); }; export const route: Route = { @@ -72,12 +72,12 @@ async function handler(ctx) { let items = $('.center-center-jiazi') .find('a[title]') .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem & { link: string } => { + const $item = $(item); return { - title: item.attr('title'), - link: `https:${item.attr('href')}`, + title: $item.attr('title')!, + link: `https:${$item.attr('href')}`, }; }); @@ -100,7 +100,7 @@ async function handler(ctx) { item.author = content('.uname, .user-name').first().text(); item.description = content('.post-cont').first().html() || content('.thread-cont').html(); - item.pubDate = timezone(parseDate(content('.cont-top-left meta').attr('content')), 8); + item.pubDate = timezone(parseDate(content('.cont-top-left meta').attr('content')!), 8); return item; }) diff --git a/lib/routes/1lou/index.ts b/lib/routes/1lou/index.ts index 166c57a10c..26624596d2 100644 --- a/lib/routes/1lou/index.ts +++ b/lib/routes/1lou/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Language, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -13,7 +13,7 @@ export const handler = async (ctx) => { const limit = ctx.req.query('limit') ? Number(ctx.req.query('limit')) : 50; const queryString = Object.entries(ctx.req.query()) - .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`) + .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value as string)}`) .join('&'); const currentUrl = new URL(`${params && params.endsWith('.htm') ? params : `${params}.htm`}${queryString ? `?${queryString}` : ''}`, rootUrl).href; @@ -27,24 +27,24 @@ export const handler = async (ctx) => { let items = $('li.media.thread.tap:not(li.hidden-sm)') .slice(0, limit) .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem & { link: string } => { + const $item = $(item); - const subjectEl = item.find('div.subject').children('a').first(); + const subjectEl = $item.find('div.subject').children('a').first(); return { title: subjectEl.text(), - pubDate: timezone(parseDate(item.find('span.date').text()), 8), - link: new URL(subjectEl.prop('href'), rootUrl).href, + pubDate: timezone(parseDate($item.find('span.date').text()), 8), + link: new URL(subjectEl.prop('href')!, rootUrl).href, category: [ - item.find('a.text-secondary').text().replaceAll('[]', ''), - ...item + $item.find('a.text-secondary').text().replaceAll('[]', ''), + ...$item .find('a.badge') .toArray() .map((c) => $(c).text()), ].filter(Boolean), - author: item.find('a.username').text(), - language, + author: $item.find('a.username').text(), + language: language as Language, }; }); @@ -59,7 +59,7 @@ export const handler = async (ctx) => { if (title) { const description = $$('div.message.break-all').html(); - const image = new URL($$('img').first().prop('src'), rootUrl).href; + const image = new URL($$('img').first().prop('src')!, rootUrl).href; item.title = title; item.description = description; @@ -73,14 +73,14 @@ export const handler = async (ctx) => { }; item.image = image; item.banner = image; - item.language = language; + item.language = language as Language; const torrents = $$('ul.attachlist li a'); if (torrents.length > 0) { const torrent = torrents.first(); - item.enclosure_url = new URL(torrent.prop('href'), rootUrl).href; + item.enclosure_url = new URL(torrent.prop('href')!, rootUrl).href; item.enclosure_type = 'application/x-bittorrent'; item.enclosure_title = torrent.text(); } @@ -92,7 +92,7 @@ export const handler = async (ctx) => { ); const author = 'BT 之家 1LOU 站'; - const image = new URL($('img.logo-2').prop('src'), rootUrl).href; + const image = new URL($('img.logo-2').prop('src')!, rootUrl).href; return { title: `${$('title').text().split(/-/, 1)[0]} - ${author}`, @@ -102,7 +102,7 @@ export const handler = async (ctx) => { allowEmpty: true, image, author, - language, + language: language as Language, }; }; @@ -138,9 +138,9 @@ export const route: Route = { { source: ['1lou.me/:params'], target: (_, url) => { - url = new URL(url); + const parsedUrl = new URL(url); - return `/1lou${url.href.replace(rootUrl, '')}`; + return `/1lou${parsedUrl.href.replace(rootUrl, '')}`; }, }, ], diff --git a/lib/routes/1x/index.tsx b/lib/routes/1x/index.tsx index b89d21b679..5472dc0396 100644 --- a/lib/routes/1x/index.tsx +++ b/lib/routes/1x/index.tsx @@ -2,7 +2,7 @@ import { load } from 'cheerio'; import { raw } from 'hono/html'; import { renderToString } from 'hono/jsx/dom/server'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import got from '@/utils/got'; export const handler = async (ctx) => { @@ -27,11 +27,11 @@ export const handler = async (ctx) => { .slice(0, limit) .toArray() .map((item) => { - item = $(item); + const $item = $(item); - const title = item.find('span.photos-feed-data-title').first().text() || 'Untitled'; - const image = item.find('img').prop('src'); - const author = item.find('span.photos-feed-data-name').first().text(); + const title = $item.find('span.photos-feed-data-title').first().text() || 'Untitled'; + const image = $item.find('img').prop('src'); + const author = $item.find('span.photos-feed-data-name').first().text(); const text = `${title} by ${author}`; @@ -46,7 +46,7 @@ export const handler = async (ctx) => { ); - const id = item.find('img[id]').prop('id').split(/-/).pop(); + const id = $item.find('img[id]').prop('id').split(/-/).pop(); const guid = `1x-${id}`; return { @@ -62,14 +62,14 @@ export const handler = async (ctx) => { }, image, banner: image, - language, + language: language as Language, enclosure_url: image, enclosure_type: image ? `image/${image.split(/\./).pop()}` : undefined, enclosure_title: title, }; }); - const image = new URL($('img.themedlogo').prop('src'), rootUrl).href; + const image = new URL($('img.themedlogo').prop('src')!, rootUrl).href; return { title: $('title').text(), @@ -79,7 +79,7 @@ export const handler = async (ctx) => { allowEmpty: true, image, author: $('meta[property="og:site_name"]').prop('content'), - language, + language: language as Language, }; }; diff --git a/lib/routes/2048/index.tsx b/lib/routes/2048/index.tsx index 6feaef9741..b032a471a7 100644 --- a/lib/routes/2048/index.tsx +++ b/lib/routes/2048/index.tsx @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; import { parseDate } from '@/utils/parse-date'; @@ -71,7 +71,7 @@ async function handler(ctx) { const onclickValue = $('.button').first().attr('onclick'); const targetUrl = onclickValue?.match(/window\.open\('([^']+)'/)?.[1]; - return { url: new URL(targetUrl, 'https://2048.info').href }; + return { url: new URL(targetUrl!, 'https://2048.info').href }; }); // 获取重定向后的url const redirectResponse = await ofetch.raw(domainInfo.url); @@ -109,13 +109,13 @@ async function handler(ctx) { .last() .nextAll('.tr3') .toArray() - .map((item) => { - item = $(item).find('a.subject'); + .map((item): DataItem & { link: string; guid: string } => { + const $item = $(item).find('a.subject'); return { - title: item.text(), - link: `${currentHost}/${item.attr('href')}`, - guid: `${rootUrl}/2048/${item.attr('href')}`, + title: $item.text(), + link: `${currentHost}/${$item.attr('href')}`, + guid: `${rootUrl}/2048/${$item.attr('href')}`, }; }) .filter((item) => !item.link.includes('undefined')); @@ -143,7 +143,7 @@ async function handler(ctx) { }); item.author = content('.fl.black').first().text(); - item.pubDate = timezone(parseDate(content('span.fl.gray').first().attr('title')), 8); + item.pubDate = timezone(parseDate(content('span.fl.gray').first().attr('title')!), 8); const readTpc = content('#read_tpc').first(); const copyLink = content('#copytext')?.first()?.text(); diff --git a/lib/routes/21caijing/channel.ts b/lib/routes/21caijing/channel.ts index f0e235293a..947b5d8d55 100644 --- a/lib/routes/21caijing/channel.ts +++ b/lib/routes/21caijing/channel.ts @@ -3,7 +3,7 @@ import { load } from 'cheerio'; import type { Context } from 'hono'; import InvalidParameterError from '@/errors/types/invalid-parameter'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -110,7 +110,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: updated ? parseDate(updated, 'X') : undefined, - language, + language: language as Language, }; return processedItem; @@ -124,7 +124,7 @@ export const handler = async (ctx: Context): Promise => { } return cache.tryGet(item.link, async (): Promise => { - const detailResponse = await ofetch(item.link); + const detailResponse = await ofetch(item.link!); const $$: CheerioAPI = load(detailResponse); $$('div.rela-box').remove(); @@ -135,7 +135,7 @@ export const handler = async (ctx: Context): Promise => { const pubDateStr: string | undefined = $$('div.author-infos span') .text() .match(/(\d{4}-\d{2}-\d{2}\s\d{2}:\d{2})/)?.[1]; - const categories: string[] = $$('meta[name="keywords"]').attr('content')?.split(/,/) ?? item.category ?? []; + const categories: DataItem['category'] = $$('meta[name="keywords"]').attr('content')?.split(/,/) ?? item.category ?? []; const upDatedStr: string | undefined = pubDateStr; const processedItem: DataItem = { @@ -148,7 +148,7 @@ export const handler = async (ctx: Context): Promise => { text: description, }, updated: upDatedStr ? timezone(parseDate(upDatedStr), 8) : item.updated, - language, + language: language as Language, }; return { @@ -169,7 +169,7 @@ export const handler = async (ctx: Context): Promise => { item: items, allowEmpty: true, author, - language, + language: language as Language, id: targetUrl, }; }; diff --git a/lib/routes/2cycd/index.ts b/lib/routes/2cycd/index.ts index 453587ef9f..48a61e5ea3 100644 --- a/lib/routes/2cycd/index.ts +++ b/lib/routes/2cycd/index.ts @@ -1,7 +1,7 @@ import { load } from 'cheerio'; import iconv from 'iconv-lite'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -45,10 +45,10 @@ async function handler(ctx) { const list = $('tbody[id^="normalthread_"]') .toArray() - .map((item) => { - item = $(item); - const xst = item.find('a.s.xst'); - const author = item.find('td.by cite a').eq(0).text(); + .map((item): DataItem => { + const $item = $(item); + const xst = $item.find('a.s.xst'); + const author = $item.find('td.by cite a').eq(0).text(); return { title: xst.text(), link: xst.attr('href'), @@ -58,7 +58,7 @@ async function handler(ctx) { // console.log(list); const items = await Promise.all( list.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const detailResponse = await got(item.link, { responseType: 'buffer', }); @@ -67,7 +67,7 @@ async function handler(ctx) { const first_post = content('td[id^="postmessage_"]').first(); const dateobj = content('em[id^="authorposton"]').first(); item.description = first_post.html(); - item.pubDate = timezone(parseDate(dateobj.find('span').attr('title'), 'YYYY-M-D HH:mm:ss'), 8); + item.pubDate = timezone(parseDate(dateobj.find('span').attr('title')!, 'YYYY-M-D HH:mm:ss'), 8); return item; }) diff --git a/lib/routes/36kr/utils.ts b/lib/routes/36kr/utils.ts index 918ee0971b..81eba1dac2 100644 --- a/lib/routes/36kr/utils.ts +++ b/lib/routes/36kr/utils.ts @@ -42,7 +42,7 @@ export const getWafTokenId = () => const payload = $('script') .text() .match(/atob\('(.*?)'\)\),/)?.[1]; - const response = solveWafChallenge(payload); + const response = solveWafChallenge(payload!); const tokenIdResponse = await ofetch.raw(rootUrl, { headers: { diff --git a/lib/routes/3dmgame/game.ts b/lib/routes/3dmgame/game.ts index f8996f4aaa..6a643cee49 100644 --- a/lib/routes/3dmgame/game.ts +++ b/lib/routes/3dmgame/game.ts @@ -33,12 +33,12 @@ async function handler(ctx) { const listSelector = type === 'resource' ? $('.ZQ_Left .Llis_4 .lis li, .zq_left .rigtbox7 li').toArray() : $('.ZQ_Left .lis, .zq_left .newsleft li').toArray(); const list = listSelector.map((i) => { - i = $(i); - const a = i.find('a[href]').last(); - const time = i.find('.time'); + const $i = $(i); + const a = $i.find('a[href]').last(); + const time = $i.find('.time'); return { title: a.text(), - description: i.find('.miaoshu').text(), + description: $i.find('.miaoshu').text(), link: a.attr('href'), pubDate: time.length ? parseDate(time.text().trim()) : null, // 2020-12-31 }; diff --git a/lib/routes/3dmgame/news-center.ts b/lib/routes/3dmgame/news-center.ts index 2ca342d3e3..c40f588775 100644 --- a/lib/routes/3dmgame/news-center.ts +++ b/lib/routes/3dmgame/news-center.ts @@ -42,21 +42,21 @@ async function handler(ctx) { const list = $(isArcPost ? '.selectarcpost' : '.selectpost') .toArray() .map((item) => { - item = $(item); + const $item = $(item); if (isArcPost) { return { - title: item.find('.bt').text(), - link: item.attr('href'), - description: item.find('p').text(), - pubDate: timezone(parseDate(item.find('.time').text()), 8), + title: $item.find('.bt').text(), + link: $item.attr('href'), + description: $item.find('p').text(), + pubDate: timezone(parseDate($item.find('.time').text()), 8), }; } - const a = item.find('.text a'); + const a = $item.find('.text a'); return { title: a.first().text(), link: a.attr('href'), - description: item.find('.miaoshu').text(), - pubDate: timezone(parseDate(item.find('.time').text()), 8), + description: $item.find('.miaoshu').text(), + pubDate: timezone(parseDate($item.find('.time').text()), 8), }; }); diff --git a/lib/routes/3dmgame/utils.ts b/lib/routes/3dmgame/utils.ts index fff6bccaf3..51130925cb 100644 --- a/lib/routes/3dmgame/utils.ts +++ b/lib/routes/3dmgame/utils.ts @@ -12,9 +12,9 @@ const parseArticle = (item) => if (item.link.startsWith('https://dl.3dmgame.com/')) { const lis = $('.patchtop .lis'); - const [, category, pubDate, author] = lis.text().match(/补丁类型:([^\n]*)\n.*整理时间:([^\n]*)\n.*补丁制作:([^\n]*)\n/s); + const [, category, pubDate, author] = lis.text().match(/补丁类型:([^\n]*)\n.*整理时间:([^\n]*)\n.*补丁制作:([^\n]*)\n/s)!; - item.description = lis.html() + $('.L_title').html() + $('.GmL_1').html(); + item.description = lis.html()! + $('.L_title').html()! + $('.GmL_1').html(); item.category = category; item.pubDate = timezone(parseDate(pubDate), 8); item.author = author; diff --git a/lib/routes/423down/index.ts b/lib/routes/423down/index.ts index 84ad2ab49d..c2b6c15a07 100644 --- a/lib/routes/423down/index.ts +++ b/lib/routes/423down/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -24,19 +24,19 @@ export const handler = async (ctx) => { let items = $('ul.excerpt li') .toArray() .filter((item) => { - item = $(item); + const $item = $(item); - const link = item.find('h2 a').prop('href'); - const isAdItem = item.find('span.cat').text().includes('423Down'); + const link = $item.find('h2 a').prop('href'); + const isAdItem = $item.find('span.cat').text().includes('423Down'); - return new RegExp(domain).test(link) && !isAdItem; + return new RegExp(domain).test(link!) && !isAdItem; }) .slice(0, limit) .map((item) => { - item = $(item); + const $item = $(item); - const title = item.find('h2').text(); - const image = item.find('a.pic img').prop('src'); + const title = $item.find('h2').text(); + const image = $item.find('a.pic img').prop('src'); const description = renderDescription({ images: image ? [ @@ -46,25 +46,25 @@ export const handler = async (ctx) => { }, ] : undefined, - intro: item.find('div.note').text(), + intro: $item.find('div.note').text(), }); return { title, description, - pubDate: parseDate(item.find('span.time').text(), 'MM-DD'), - link: item.find('h2 a').prop('href'), - category: item + pubDate: parseDate($item.find('span.time').text(), 'MM-DD'), + link: $item.find('h2 a').prop('href'), + category: $item .find('span.cat a') .toArray() .map((c) => $(c).text()), content: { html: description, - text: item.find('div.note').text(), + text: $item.find('div.note').text(), }, image, banner: image, - language, + language: language as Language, enclosure_url: image, enclosure_type: image ? `image/${image.split(/\./).pop()}` : undefined, enclosure_title: title, @@ -73,13 +73,13 @@ export const handler = async (ctx) => { items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const { data: detailResponse } = await got(item.link); const $$ = load(detailResponse); const title = $$('h1.meta-tit a').text(); - const description = item.description + renderDescription({ description: $$('div.entry').html() }); + const description = item.description + renderDescription({ description: $$('div.entry').html() ?? undefined }); item.title = title; item.description = description; @@ -91,7 +91,7 @@ export const handler = async (ctx) => { html: description, text: $$('div.entry').text(), }; - item.language = language; + item.language = language as Language; return item; }) @@ -109,7 +109,7 @@ export const handler = async (ctx) => { allowEmpty: true, image, author: title.split(/-/).pop()?.trim(), - language, + language: language as Language, }; }; diff --git a/lib/routes/4ksj/forum.tsx b/lib/routes/4ksj/forum.tsx index f4f811c68f..9448e56210 100644 --- a/lib/routes/4ksj/forum.tsx +++ b/lib/routes/4ksj/forum.tsx @@ -2,7 +2,7 @@ import { load } from 'cheerio'; import { raw } from 'hono/html'; import { renderToString } from 'hono/jsx/dom/server'; -import type { Route } from '@/types'; +import type { DataItem, Language, Route } from '@/types'; import cache from '@/utils/cache'; import md5 from '@/utils/md5'; import ofetch from '@/utils/ofetch'; @@ -98,11 +98,12 @@ async function handler(ctx) { let items = $('div.nex_cmo_piv a') .slice(0, limit) .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem & { link: string } => { + const $item = $(item); return { - link: new URL(item.prop('href'), rootUrl).href, + link: new URL($item.prop('href')!, rootUrl).href, + title: '', }; }); @@ -145,28 +146,28 @@ async function handler(ctx) { $$('div.nex_drama_intros em').first().remove(); $$('strong font').each((_, el) => { - el = $$(el); + const $el = $$(el); - el.parent().remove(); + $el.parent().remove(); }); const title = $$('div.nex_drama_Top h5').text(); const description = $$('div.nex_drama_intros').html(); const picture = $$('div.nex_drama_pic') - .html() + .html()! .match(/background:url\((.*?)\)/)?.[1] ?? ''; const details = $$('li.nex_drama_Detail_li, li.nex_drama_Detail_lis dd') .toArray() .map((li) => { - li = $$(li); + const $li = $$(li); - const key = li + const key = $li .find('em') .text() .replaceAll(/:|\s/g, ''); - const value = li.find('span').length === 0 ? li.contents().last().text().trim() : li.find('span').text().trim(); + const value = $li.find('span').length === 0 ? $li.contents().last().text().trim() : $li.find('span').text().trim(); return { [key]: value }; }); @@ -177,10 +178,10 @@ async function handler(ctx) { ? $$('td.t_f strong') .toArray() .map((l) => { - l = $$(l); + const $l = $$(l); - const title = l.contents().first().text(); - const link = l.next().prop('href') ?? l.nextUntil('a').next().prop('href'); + const title = $l.contents().first().text(); + const link = $l.next().prop('href') ?? $l.nextUntil('a').next().prop('href'); item.enclosure_url ??= link; item.enclosure_type ??= 'application/x-bittorrent'; @@ -188,7 +189,7 @@ async function handler(ctx) { return { title, - tags: l + tags: $l .contents() .last() .text() @@ -199,15 +200,15 @@ async function handler(ctx) { : $$('div.newfujian') .toArray() .map((l) => { - l = $$(l); + const $l = $$(l); return { - title: l.find('p.filename').prop('title') || l.find('p.filename').text(), - tags: l + title: $l.find('p.filename').prop('title') || $l.find('p.filename').text(), + tags: $l .find('div.fileaq') .text() .match(/【(.*?)】/g), - link: l.find('div.down_2 a').prop('href'), + link: $l.find('div.down_2 a').prop('href'), }; }); @@ -238,7 +239,7 @@ async function handler(ctx) { links, }); item.pubDate = timezone(parseDate(pubDate, 'YYYY-M-D HH:mm:ss'), 8); - item.category = Object.values(mergedDetails) + item.category = Object.values(mergedDetails) .flatMap((c) => c.split(/\s/)) .filter(Boolean); item.author = mergedDetails['导演']; @@ -268,6 +269,6 @@ async function handler(ctx) { allowEmpty: true, image, author: $('meta[name="application-name"]').prop('content'), - language, + language: language as Language, }; } diff --git a/lib/routes/50forum/zhuanjia.ts b/lib/routes/50forum/zhuanjia.ts index 5cdf4c6dfd..cd23639926 100644 --- a/lib/routes/50forum/zhuanjia.ts +++ b/lib/routes/50forum/zhuanjia.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -34,21 +34,21 @@ async function handler() { }); const data = response.data; if (!data) { - return; + return null; } const $ = load(data); let out = $('div.container div.list_list.mtop10 ul li') .find('a') .toArray() - .map((item) => { - item = $(item); - const link = rootUrl + item.attr('href'); + .map((item): DataItem & { link: string } => { + const $item = $(item); + const link = rootUrl + $item.attr('href'); const reg = /^(.+) - (.*) - (.+)$/; - const keyword = reg.exec(item.text().trim()); + const keyword = reg.exec($item.text().trim()); return { - title: keyword[1], - author: keyword[2], - pubDate: timezone(parseDate(keyword[3], 'YYYY-MM-DD'), 8), + title: keyword![1], + author: keyword![2], + pubDate: timezone(parseDate(keyword![3], 'YYYY-MM-DD'), 8), link, }; }); diff --git a/lib/routes/51cto/recommend.ts b/lib/routes/51cto/recommend.ts index ee8b1b85bf..cf92eeaac4 100644 --- a/lib/routes/51cto/recommend.ts +++ b/lib/routes/51cto/recommend.ts @@ -6,6 +6,7 @@ import got from '@/utils/got'; import logger from '@/utils/logger'; import ofetch from '@/utils/ofetch'; import { parseDate } from '@/utils/parse-date'; +import timezone from '@/utils/timezone'; import { getToken, sign } from './utils'; @@ -53,7 +54,7 @@ async function getFullcontent(item, cookie = '') { return { title: item.title, link: item.url, - pubDate: parseDate(item.pubdate, 8), + pubDate: timezone(parseDate(item.pubdate), 8), description: fullContent || item.abstract, // Return item.abstract if fullContent is null }; } diff --git a/lib/routes/51read/article.ts b/lib/routes/51read/article.ts index b8556f6db9..68591d898c 100644 --- a/lib/routes/51read/article.ts +++ b/lib/routes/51read/article.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { DataItem, Route } from '@/types'; +import type { DataItem, Language, Route } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -57,7 +57,7 @@ async function handler(ctx) { item, image: $book('.bi-img img').attr('src'), author: $book('.bi-wt a').text(), - language: 'zh-cn', + language: 'zh-CN' as Language, }; } diff --git a/lib/routes/56kog/util.tsx b/lib/routes/56kog/util.tsx index 985c311179..ea01d1a68a 100644 --- a/lib/routes/56kog/util.tsx +++ b/lib/routes/56kog/util.tsx @@ -2,6 +2,7 @@ import { load } from 'cheerio'; import { renderToString } from 'hono/jsx/dom/server'; import iconv from 'iconv-lite'; +import type { DataItem, Language } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -18,21 +19,21 @@ const fetchItems = async (limit, currentUrl) => { let items = $('p.line') .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); - const a = item.find('a'); + const a = $item.find('a'); return { title: a.text(), - link: new URL(a.prop('href'), rootUrl).href, - author: item.find('span').last().text(), + link: new URL(a.prop('href')!, rootUrl).href, + author: $item.find('span').last().text(), }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { try { const { data: detailResponse } = await got(item.link, { responseType: 'buffer', @@ -42,16 +43,16 @@ const fetchItems = async (limit, currentUrl) => { const details = content('div.mohe-content p') .toArray() - .map((detail) => { - detail = content(detail); - const as = detail.find('a'); + .map((detail): { label: string; value: any } => { + const $detail = content(detail); + const as = $detail.find('a'); return { - label: detail.find('span.c-l-depths').text().split(/:/, 1)[0], + label: $detail.find('span.c-l-depths').text().split(/:/, 1)[0], value: as.length === 0 ? content( - detail + $detail .contents() .toArray() .find((c) => c.nodeType === 3) @@ -59,27 +60,27 @@ const fetchItems = async (limit, currentUrl) => { .text() .trim() : { - href: new URL(as.first().prop('href'), rootUrl).href, + href: new URL(as.first().prop('href')!, rootUrl).href, text: as.first().text().trim(), }, }; }); - const pubDate = details.find((detail) => detail.label === '更新').value; + const pubDate = details.find((detail) => detail.label === '更新')!.value; item.title = content('h1').contents().first().text(); item.description = renderDescription({ images: [ { - src: new URL(content('a.mohe-imgs img').prop('src'), rootUrl).href, + src: new URL(content('a.mohe-imgs img').prop('src')!, rootUrl).href, alt: item.title, }, ], details, }); - item.author = details.find((detail) => detail.label === '作者').value; - item.category = [details.find((detail) => detail.label === '状态').value, details.find((detail) => detail.label === '类型').value.text].filter(Boolean); - item.guid = `56kog-${item.link.match(/\/(\d+)\.html$/)[1]}#${pubDate}`; + item.author = details.find((detail) => detail.label === '作者')!.value; + item.category = [details.find((detail) => detail.label === '状态')!.value, details.find((detail) => detail.label === '类型')!.value.text].filter(Boolean); + item.guid = `56kog-${item.link!.match(/\/(\d+)\.html$/)![1]}#${pubDate}`; item.pubDate = timezone(parseDate(pubDate), 8); } catch { // no-empty @@ -97,7 +98,7 @@ const fetchItems = async (limit, currentUrl) => { title: $('title').text(), link: currentUrl, description: $('meta[name="description"]').prop('content'), - language: $('html').prop('lang'), + language: $('html').prop('lang') as Language, icon, logo: icon, subtitle: $('meta[name="keywords"]').prop('content'), diff --git a/lib/routes/591/list.tsx b/lib/routes/591/list.tsx index 76bbe7c99a..06e36175bb 100644 --- a/lib/routes/591/list.tsx +++ b/lib/routes/591/list.tsx @@ -24,7 +24,7 @@ function appendRentalAPIParams(urlString) { } async function getToken() { - const html = await client('https://rent.591.com.tw').text(); + const html = await (client('https://rent.591.com.tw') as any).text(); const $ = load(html); const csrfToken = $('meta[name="csrf-token"]').attr('content'); @@ -39,12 +39,14 @@ async function getToken() { async function getHouseList(houseListURL) { const csrfToken = await getToken(); - const data = await client({ - url: houseListURL, - headers: { - 'X-CSRF-TOKEN': csrfToken, - }, - }).json(); + const data = await ( + client({ + url: houseListURL, + headers: { + 'X-CSRF-TOKEN': csrfToken, + }, + }) as any + ).json(); const { data: { data: houseList }, diff --git a/lib/routes/5music/index.ts b/lib/routes/5music/index.ts index bcfd1c3af7..dd8946c948 100644 --- a/lib/routes/5music/index.ts +++ b/lib/routes/5music/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -84,6 +84,6 @@ async function handler(ctx) { title: '五大唱片 - 新货上架', link: url, item: items, - language: 'zh-tw', + language: 'zh-TW' as Language, }; } diff --git a/lib/routes/69shu/article.ts b/lib/routes/69shu/article.ts index b01f213223..37ec9106c8 100644 --- a/lib/routes/69shu/article.ts +++ b/lib/routes/69shu/article.ts @@ -45,7 +45,7 @@ export const route: Route = { item, image: $('.bookimg2>img').attr('src'), author: $('.booknav2>p:first-of-type>a').text(), - language: 'zh-cn', + language: 'zh-CN', }; }, }; diff --git a/lib/routes/6park/index.ts b/lib/routes/6park/index.ts index fd6123acce..0d10a8feb2 100644 --- a/lib/routes/6park/index.ts +++ b/lib/routes/6park/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -45,19 +45,20 @@ async function handler(ctx) { let items = $('#d_list ul li, #thread_list li, .t_l .t_subject') .toArray() .slice(0, limit) - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); - const a = item.find('a').first(); + const a = $item.find('a').first(); return { link: `${rootUrl}/${id}/${a.attr('href')}`, + title: '', }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const detailResponse = await got({ method: 'get', url: item.link, @@ -69,7 +70,7 @@ async function handler(ctx) { item.author = detailResponse.data.match(/送交者:[^>]*>([^<]*)<\/a>/)[1].trim(); item.pubDate = timezone(parseDate(detailResponse.data.match(/于 (.*) 已读/)[1], 'YYYY-MM-DD h:m'), 8); item.description = content('pre') - .html() + .html()! .replaceAll('

', '') .replaceAll(/6park.com<\/font>/g, ''); diff --git a/lib/routes/6park/news.ts b/lib/routes/6park/news.ts index 2e6ffab358..075c49904d 100644 --- a/lib/routes/6park/news.ts +++ b/lib/routes/6park/news.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -58,23 +58,23 @@ async function handler(ctx) { let items = $('#d_list ul li, #thread_list li, .t_l .t_subject') .toArray() .slice(0, limit) - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); - const a = item.find('a').first(); + const a = $item.find('a').first(); const link = a.attr('href'); return { title: a.text(), - link: link.startsWith('http') ? link : `${rootUrl}/${link.startsWith('view') ? `newspark/${link}` : link}`, + link: link!.startsWith('http') ? link : `${rootUrl}/${link!.startsWith('view') ? `newspark/${link}` : link}`, }; }); items = await Promise.all( items - .filter((item) => /6parknews\.com/.test(item.link)) + .filter((item) => /6parknews\.com/.test(item.link!)) .map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { try { const detailResponse = await got({ method: 'get', @@ -88,7 +88,7 @@ async function handler(ctx) { item.title = content('h2').text(); item.author = matches[1].trim(); item.pubDate = timezone(parseDate(matches[2], 'YYYY-MM-DD h:m'), 8); - item.description = content('#shownewsc').html().replaceAll('

', ''); + item.description = content('#shownewsc').html()!.replaceAll('

', ''); } catch { // no-empty } diff --git a/lib/routes/6v123/index.ts b/lib/routes/6v123/index.ts index 54e55a5e65..95ee35940c 100644 --- a/lib/routes/6v123/index.ts +++ b/lib/routes/6v123/index.ts @@ -4,7 +4,7 @@ import type { Element } from 'domhandler'; import type { Context } from 'hono'; import iconv from 'iconv-lite'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -28,7 +28,7 @@ export const handler = async (ctx: Context): Promise => { let items: DataItem[] = $('ul.list li') .slice(0, limit) .toArray() - .map((el): Element => { + .map((el) => { const $el: Cheerio = $(el); const title: string = $el.find('a').text(); @@ -47,7 +47,7 @@ export const handler = async (ctx: Context): Promise => { guid, id: guid, updated: upDatedStr ? parseDate(upDatedStr, ['MM-DD', 'YYYY-MM-DD']) : undefined, - language, + language: language as Language, }; return processedItem; @@ -60,7 +60,7 @@ export const handler = async (ctx: Context): Promise => { } return cache.tryGet(item.link, async (): Promise => { - const detailResponse = await ofetch(item.link, { + const detailResponse = await ofetch(item.link!, { responseType: 'arrayBuffer', }); const $$: CheerioAPI = load(iconv.decode(Buffer.from(detailResponse), encoding)); @@ -92,7 +92,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: upDatedStr ? parseDate(upDatedStr) : item.updated, - language, + language: language as Language, }; const $enclosureEl: Cheerio = $$('td a[href^="magnet"]').last(); @@ -125,7 +125,7 @@ export const handler = async (ctx: Context): Promise => { item: items, allowEmpty: true, image: new URL('images/logo.gif', baseUrl).href, - language, + language: language as Language, id: targetUrl, }; }; diff --git a/lib/routes/78dm/index.ts b/lib/routes/78dm/index.ts index fdebe88264..1cafb0a137 100644 --- a/lib/routes/78dm/index.ts +++ b/lib/routes/78dm/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Language, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -24,12 +24,12 @@ export const handler = async (ctx) => { let items = $('section.box-content div.card a.card-title') .slice(0, limit) .toArray() - .map((item) => { - item = $(item).parent(); + .map((item): DataItem => { + const $item = $(item).parent(); - const title = item.find('a.card-title').text(); + const title = $item.find('a.card-title').text(); - const src = item.find('a.card-image img').prop('data-src'); + const src = $item.find('a.card-image img').prop('data-src'); const image = src?.startsWith('//') ? `https:${src}` : src; const description = renderDescription({ @@ -42,9 +42,9 @@ export const handler = async (ctx) => { ] : undefined, }); - const pubDate = item.find('div.card-info span.item').last().text(); + const pubDate = $item.find('div.card-info span.item').last().text(); - const href = item.find('a.card-title').prop('href'); + const href = $item.find('a.card-title').prop('href'); return { title, @@ -53,22 +53,22 @@ export const handler = async (ctx) => { link: href?.startsWith('//') ? `https:${href}` : href, category: [ ...new Set([ - ...item + ...$item .find('span.tag-title') .toArray() .map((c) => $(c).text()), - item.find('div.card-info span.item').first().text(), + $item.find('div.card-info span.item').first().text(), ]), ].filter(Boolean), image, banner: image, - language, + language: language as Language, }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const { data: detailResponse } = await got(item.link); const $$ = load(detailResponse); @@ -76,18 +76,18 @@ export const handler = async (ctx) => { $$('i.p-status').remove(); $$('div.image-text-content p img.lazy').each((_, el) => { - el = $$(el); + const $el = $$(el); - const src = el.prop('data-src'); + const src = $el.prop('data-src'); const image = src?.startsWith('//') ? `https:${src}` : src; - el.parent().replaceWith( + $el.parent().replaceWith( renderDescription({ images: image ? [ { src: image, - alt: el.prop('title') ?? '', + alt: $el.prop('title') ?? '', }, ] : undefined, @@ -104,13 +104,13 @@ export const handler = async (ctx) => { item.title = title; item.description = description; - item.pubDate = timezone(parseDate($$('p.push-time').text().split(/:/).pop()), 8); + item.pubDate = timezone(parseDate($$('p.push-time').text().split(/:/).pop()!), 8); item.author = $$('a.push-username').contents().first().text(); item.content = { html: description, text: $$('div.image-text-content').first().text(), }; - item.language = language; + item.language = language as Language; return item; }) @@ -118,7 +118,7 @@ export const handler = async (ctx) => { ); const title = $('title').text(); - const image = new URL($('a.logo img').prop('src'), rootUrl).href; + const image = new URL($('a.logo img').prop('src')!, rootUrl).href; return { title: `${title} | ${$('div.actived').text()}`, @@ -128,7 +128,7 @@ export const handler = async (ctx) => { allowEmpty: true, image, author: $('meta[property="og:site_name"]').prop('content'), - language, + language: language as Language, }; }; diff --git a/lib/routes/7mmtv/index.tsx b/lib/routes/7mmtv/index.tsx index 4104cf7092..4ebd5fa372 100644 --- a/lib/routes/7mmtv/index.tsx +++ b/lib/routes/7mmtv/index.tsx @@ -2,7 +2,7 @@ import { load } from 'cheerio'; import { raw } from 'hono/html'; import { renderToString } from 'hono/jsx/dom/server'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -64,23 +64,23 @@ async function handler(ctx) { let items = $('.video') .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem & { poster?: string; video?: string } => { + const $item = $(item); - const title = item.find('.video-title a'); + const title = $item.find('.video-title a'); return { title: title.text(), - author: item.find('.video-channel').text(), - pubDate: parseDate(item.find('.small').text()), + author: $item.find('.video-channel').text(), + pubDate: parseDate($item.find('.small').text()), link: title.attr('href'), - poster: item.find('img').attr('data-src'), - video: item.find('video').attr('data-src'), + poster: $item.find('img').attr('data-src'), + video: $item.find('video').attr('data-src'), }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const detailResponse = await got({ method: 'get', url: item.link, diff --git a/lib/routes/81/81rc/index.ts b/lib/routes/81/81rc/index.ts index 18bdf4f9aa..f5aa5e8b17 100644 --- a/lib/routes/81/81rc/index.ts +++ b/lib/routes/81/81rc/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Language, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -22,20 +22,20 @@ export const handler = async (ctx) => { let items = $('div.left-news ul li') .slice(0, limit) .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); return { - title: item.find('a').text(), - pubDate: timezone(parseDate(item.find('span').text()), 8), - link: item.find('a').prop('href'), - language, + title: $item.find('a').text(), + pubDate: timezone(parseDate($item.find('span').text()), 8), + link: $item.find('a').prop('href'), + language: language as Language, }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const { data: detailResponse } = await got(item.link); const $$ = load(detailResponse); @@ -50,7 +50,7 @@ export const handler = async (ctx) => { html: description, text: $$('div.txt').text(), }; - item.language = language; + item.language = language as Language; return item; }) @@ -68,7 +68,7 @@ export const handler = async (ctx) => { allowEmpty: true, image, author: title.split(/-/).pop()?.trim(), - language, + language: language as Language, }; }; diff --git a/lib/routes/8264/list.tsx b/lib/routes/8264/list.tsx index 3a752f13ee..7e47d64d27 100644 --- a/lib/routes/8264/list.tsx +++ b/lib/routes/8264/list.tsx @@ -2,7 +2,7 @@ import { load } from 'cheerio'; import { renderToString } from 'hono/jsx/dom/server'; import iconv from 'iconv-lite'; -import type { Route } from '@/types'; +import type { DataItem, Language, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -103,20 +103,20 @@ async function handler(ctx) { .find('a') .slice(0, limit) .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); - const link = item.prop('href'); + const link = $item.prop('href'); return { - title: item.text(), - link: link.startsWith('http') ? link : new URL(link, rootUrl).href, + title: $item.text(), + link: link!.startsWith('http') ? link : new URL(link!, rootUrl).href, }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const { data: detailResponse } = await got(item.link, { responseType: 'buffer', }); @@ -127,7 +127,7 @@ async function handler(ctx) { content('i.pstatus').remove(); content('div.crly').remove(); - const pubDate = content('span.pub-time').text() || content('span.fby span').first().prop('title') || content('span.fby').first().text().split('发表于').pop().trim(); + const pubDate = content('span.pub-time').text() || content('span.fby span').first().prop('title') || content('span.fby').first().text().split('发表于').pop()!.trim(); content('img').each((_, el) => { content(el).replaceWith( @@ -160,7 +160,7 @@ async function handler(ctx) { title: `${$('span.country, h2').text()} - ${description.split(',').pop()}`, link: currentUrl, description, - language: 'zh-cn', + language: 'zh-CN' as Language, icon, logo: icon, subtitle: $('meta[name="keywords"]').prop('content').trim(), diff --git a/lib/routes/8world/index.ts b/lib/routes/8world/index.ts index 285d8d1bd8..7e19b23152 100644 --- a/lib/routes/8world/index.ts +++ b/lib/routes/8world/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import { getSubPath } from '@/utils/common-utils'; import got from '@/utils/got'; @@ -41,18 +41,18 @@ export async function handler(ctx) { let items = $('div[data-column="Two-Third"] .article-title .article-link') .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); return { - title: item.text(), - link: `${rootUrl}${item.attr('href')}`, + title: $item.text(), + link: `${rootUrl}${$item.attr('href')}`, }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const detailResponse = await got({ method: 'get', url: item.link, @@ -61,12 +61,12 @@ export async function handler(ctx) { const content = load(detailResponse.data); item.description = content('.text-long').html(); - item.title = content('meta[name="cXenseParse:mdc-title"]').attr('content'); + item.title = content('meta[name="cXenseParse:mdc-title"]').attr('content')!; item.author = content('meta[name="cXenseParse:author"]').attr('content'); - item.pubDate = parseDate(content('meta[name="cXenseParse:recs:publishtime"]').attr('content')); + item.pubDate = parseDate(content('meta[name="cXenseParse:recs:publishtime"]').attr('content')!); item.category = content('meta[name="cXenseParse:mdc-keywords"]') .toArray() - .map((keyword) => content(keyword).attr('content')); + .map((keyword) => content(keyword).attr('content')!); return item; }) diff --git a/lib/routes/91porn/author.ts b/lib/routes/91porn/author.ts index 6ab2df39f0..44f41fb526 100644 --- a/lib/routes/91porn/author.ts +++ b/lib/routes/91porn/author.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -53,25 +53,25 @@ async function handler(ctx) { let items = $('.row .well') .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem & { poster?: string } => { + const $item = $(item); return { - title: item.find('.video-title').text(), - link: item.find('a').attr('href'), - poster: item.find('.img-responsive').attr('src'), + title: $item.find('.video-title').text(), + link: $item.find('a').attr('href'), + poster: $item.find('.img-responsive').attr('src'), }; }); items = await Promise.all( items.map((item) => - cache.tryGet(`91porn:${lang}:${new URL(item.link).searchParams.get('viewkey')}`, async () => { + cache.tryGet(`91porn:${lang}:${new URL(item.link!).searchParams.get('viewkey')}`, async () => { const { data } = await got(item.link); const $ = load(data); item.pubDate = parseDate($('.title-yakov').eq(0).text(), 'YYYY-MM-DD'); item.description = renderIndexDescription({ - link: item.link, - poster: item.poster, + link: item.link!, + poster: item.poster!, }); item.author = $('.title-yakov a span').text(); delete item.poster; diff --git a/lib/routes/91porn/index.ts b/lib/routes/91porn/index.ts index d5998e5d12..57912775da 100644 --- a/lib/routes/91porn/index.ts +++ b/lib/routes/91porn/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -56,25 +56,25 @@ async function handler(ctx) { let items = $('.row .well') .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem & { poster?: string } => { + const $item = $(item); return { - title: item.find('.video-title').text(), - link: item.find('a').attr('href'), - poster: item.find('.img-responsive').attr('src'), + title: $item.find('.video-title').text(), + link: $item.find('a').attr('href'), + poster: $item.find('.img-responsive').attr('src'), }; }); items = await Promise.all( items.map((item) => - cache.tryGet(`91porn:${lang}:${new URL(item.link).searchParams.get('viewkey')}`, async () => { + cache.tryGet(`91porn:${lang}:${new URL(item.link!).searchParams.get('viewkey')}`, async () => { const { data } = await got(item.link); const $ = load(data); item.pubDate = parseDate($('.title-yakov').eq(0).text(), 'YYYY-MM-DD'); item.description = renderIndexDescription({ - link: item.link, - poster: item.poster, + link: item.link!, + poster: item.poster!, }); item.author = $('.title-yakov a span').text(); delete item.poster; diff --git a/lib/routes/95mm/utils.tsx b/lib/routes/95mm/utils.tsx index be22b86a9c..f9ae6d191b 100644 --- a/lib/routes/95mm/utils.tsx +++ b/lib/routes/95mm/utils.tsx @@ -1,6 +1,7 @@ import { load } from 'cheerio'; import { renderToString } from 'hono/jsx/dom/server'; +import type { DataItem } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; @@ -19,21 +20,21 @@ const ProcessItems = async (ctx, title, currentUrl) => { let items = $('div.list-body') .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); - const a = item.find('a'); + const a = $item.find('a'); return { title: a.text(), link: a.attr('href'), - guid: a.attr('href').replace('95mm.vip', '95mm.org'), + guid: a.attr('href')!.replace('95mm.vip', '95mm.org'), }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const detailResponse = await got({ method: 'get', url: item.link, diff --git a/lib/routes/9to5/subsite.ts b/lib/routes/9to5/subsite.ts index 5b8d492ab5..9898f67e07 100644 --- a/lib/routes/9to5/subsite.ts +++ b/lib/routes/9to5/subsite.ts @@ -64,7 +64,7 @@ async function handler(ctx) { const items = await Promise.all( feed.items.splice(0, limit).map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const response = await got({ method: 'get', url: item.link, @@ -72,7 +72,7 @@ async function handler(ctx) { const description = utils.ProcessFeed(response.data); const single = { - title: item.title, + title: item.title!, description, pubDate: item.pubDate, link: item.link, diff --git a/lib/routes/9to5/utils.ts b/lib/routes/9to5/utils.ts index 3a3542b1ea..6a1da82a34 100644 --- a/lib/routes/9to5/utils.ts +++ b/lib/routes/9to5/utils.ts @@ -6,7 +6,7 @@ const ProcessFeed = (data) => { const cover = $('meta[property="og:image"]'); if (cover.length > 0) { - $(``).insertBefore(content[0].firstChild); + $(``).insertBefore(content[0].firstChild!); } // remove useless DOMs diff --git a/lib/routes/a9vg/index.ts b/lib/routes/a9vg/index.ts index dc911e6cd1..0d1bf5e454 100644 --- a/lib/routes/a9vg/index.ts +++ b/lib/routes/a9vg/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Language, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -24,15 +24,15 @@ export const handler = async (ctx) => { let items = $('a.a9-rich-card-list_item') .slice(0, limit) .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); - const image = item.find('img.a9-rich-card-list_image'); - const title = item.find('div.a9-rich-card-list_label').text(); + const image = $item.find('img.a9-rich-card-list_image'); + const title = $item.find('div.a9-rich-card-list_label').text(); return { title, - link: new URL(item.prop('href'), rootUrl).href, + link: new URL($item.prop('href')!, rootUrl).href, description: renderDescription({ images: image ? [ @@ -43,28 +43,28 @@ export const handler = async (ctx) => { ] : undefined, }), - pubDate: timezone(parseDate(item.find('div.a9-rich-card-list_infos').text()), 8), - language, + pubDate: timezone(parseDate($item.find('div.a9-rich-card-list_infos').text()), 8), + language: language as Language, }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const { data: detailResponse } = await got(item.link); const $$ = load(detailResponse); $$('ignore_js_op img, p img').each((_, el) => { - el = $$(el); + const $el = $$(el); - el.parent().replaceWith( + $el.parent().replaceWith( renderDescription({ - images: el.prop('file') + images: $el.prop('file') ? [ { - src: el.prop('file'), - alt: el.next().find('div.xs0 p').first().text(), + src: $el.prop('file'), + alt: $el.next().find('div.xs0 p').first().text(), }, ] : undefined, @@ -74,7 +74,7 @@ export const handler = async (ctx) => { item.title = $$('h1.ts, div.c-article-main_content-title').text(); item.description = renderDescription({ - description: $$('td.t_f, div.c-article-main_contentraw').first().html(), + description: $$('td.t_f, div.c-article-main_contentraw').first().html() ?? undefined, }); item.author = $$('b a.blue').first().text() || @@ -96,7 +96,7 @@ export const handler = async (ctx) => { ), 8 ); - item.language = language; + item.language = language as Language; return item; }) @@ -114,7 +114,7 @@ export const handler = async (ctx) => { allowEmpty: true, image, author: title.split(/-/).pop(), - language, + language: language as Language, }; }; diff --git a/lib/routes/aa1/60s.ts b/lib/routes/aa1/60s.ts index b125d7e71a..971bc4e3ce 100644 --- a/lib/routes/aa1/60s.ts +++ b/lib/routes/aa1/60s.ts @@ -2,7 +2,7 @@ import type { CheerioAPI } from 'cheerio'; import { load } from 'cheerio'; import type { Context } from 'hono'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import ofetch from '@/utils/ofetch'; import { parseDate } from '@/utils/parse-date'; @@ -76,7 +76,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: updated ? parseDate(updated) : undefined, - language, + language: language as Language, }; return processedItem; @@ -92,7 +92,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image: $('header#header-div img').attr('src'), author: title.split(/-/).pop(), - language, + language: language as Language, id: targetUrl, }; }; diff --git a/lib/routes/aamacau/index.ts b/lib/routes/aamacau/index.ts index 5e039dcc6f..daec725567 100644 --- a/lib/routes/aamacau/index.ts +++ b/lib/routes/aamacau/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -56,18 +56,18 @@ async function handler(ctx) { const list = $('post-title a') .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); return { - title: item.text(), - link: item.attr('href'), + title: $item.text(), + link: $item.attr('href'), }; }); const items = await Promise.all( list.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const detailResponse = await got({ method: 'get', url: item.link, @@ -79,7 +79,7 @@ async function handler(ctx) { item.description = content('#contentleft').html(); item.author = content('meta[itemprop="author"]').attr('content'); - item.pubDate = parseDate(content('meta[property="article:published_time"]').attr('content')); + item.pubDate = parseDate(content('meta[property="article:published_time"]').attr('content')!); return item; }) diff --git a/lib/routes/abc/index.ts b/lib/routes/abc/index.ts index dbcd8dfc38..03ce451a64 100644 --- a/lib/routes/abc/index.ts +++ b/lib/routes/abc/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Language, Route } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; import { parseDate } from '@/utils/parse-date'; @@ -67,7 +67,7 @@ async function handler(ctx) { }); let items = response.collection.slice(0, limit).map((i) => { - const item = { + const item: DataItem = { title: i.title.children ?? i.title, link: i.link.startsWith('https://') ? i.link : new URL(i.link, rootUrl).href, description: renderDescription({ @@ -107,11 +107,11 @@ async function handler(ctx) { .children() .each((_, el) => { const element = content(el); - if (element.prop('tagName').toLowerCase() === 'figure') { + if (element.prop('tagName')!.toLowerCase() === 'figure') { element.replaceWith( renderDescription({ image: { - src: element.find('img').prop('src').split(/\?/, 1)[0], + src: element.find('img').prop('src')!.split(/\?/, 1)[0], alt: element.find('figcaption').text().trim(), }, }) @@ -178,7 +178,7 @@ async function handler(ctx) { title: $('title').first().text(), link: currentUrl, description: $('meta[property="og:description"]').prop('content'), - language: $('html').prop('lang'), + language: $('html').prop('lang') as Language, image: $('meta[property="og:image"]').prop('content').split('?', 1)[0], icon, logo: icon, diff --git a/lib/routes/abc/templates/description.tsx b/lib/routes/abc/templates/description.tsx index bd407bfaa1..5018714921 100644 --- a/lib/routes/abc/templates/description.tsx +++ b/lib/routes/abc/templates/description.tsx @@ -1,6 +1,6 @@ import { raw } from 'hono/html'; +import type { FC } from 'hono/jsx'; import { renderToString } from 'hono/jsx/dom/server'; -import type { JSX } from 'hono/jsx/jsx-runtime'; type DescriptionData = { image?: { @@ -15,7 +15,7 @@ type DescriptionData = { }; const AbcDescription = ({ image, enclosure, description }: DescriptionData) => { - const enclosureTag = enclosure?.type?.split('/', 1)[0] as keyof JSX.IntrinsicElements | undefined; + const enclosureTag = enclosure?.type?.split('/', 1)[0] as unknown as FC | undefined; return ( <> diff --git a/lib/routes/accessbriefing/index.ts b/lib/routes/accessbriefing/index.ts index 05bd4a039f..e5f98a566b 100644 --- a/lib/routes/accessbriefing/index.ts +++ b/lib/routes/accessbriefing/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -64,7 +64,7 @@ export const handler = async (ctx) => { }, image, banner: image, - language, + language: language as Language, }; }); @@ -79,7 +79,7 @@ export const handler = async (ctx) => { const description = item.description + renderDescription({ - description: $$('div.khl-article-page-storybody').html(), + description: $$('div.khl-article-page-storybody').html() ?? undefined, }); item.title = title; @@ -99,7 +99,7 @@ export const handler = async (ctx) => { ) ); - const image = new URL($('a.navbar-brand img').prop('src'), rootUrl).href; + const image = new URL($('a.navbar-brand img').prop('src')!, rootUrl).href; return { title: $('title').text(), @@ -109,7 +109,7 @@ export const handler = async (ctx) => { allowEmpty: true, image, author: $('meta[property="og:site_name"]').prop('content'), - language, + language: language as Language, }; }; diff --git a/lib/routes/accessbriefing/templates/description.tsx b/lib/routes/accessbriefing/templates/description.tsx index 7e005bb11f..ee0ee0d010 100644 --- a/lib/routes/accessbriefing/templates/description.tsx +++ b/lib/routes/accessbriefing/templates/description.tsx @@ -20,7 +20,7 @@ const AccessBriefingDescription = ({ images, intro, description }: DescriptionDa ? images.map((image) => image?.src ? (
- {image.height + {(image.height
) : null ) diff --git a/lib/routes/acfun/article.ts b/lib/routes/acfun/article.ts index ef3f183f6d..1cc2de0d34 100644 --- a/lib/routes/acfun/article.ts +++ b/lib/routes/acfun/article.ts @@ -133,7 +133,7 @@ async function handler(ctx) { const $ = load(response.data); const articleInfo = $('.main script') .text() - .match(/window.articleInfo = (.*);\n\s*window.likeDomain/)[1]; + .match(/window.articleInfo = (.*);\n\s*window.likeDomain/)![1]; const data = JSON.parse(articleInfo); item.description = data.parts[0].content; diff --git a/lib/routes/acpaa/index.ts b/lib/routes/acpaa/index.ts index 77976aa563..6fee068225 100644 --- a/lib/routes/acpaa/index.ts +++ b/lib/routes/acpaa/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Language, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -38,19 +38,19 @@ async function handler(ctx) { let items = $('div.text01 ul li a[title]') .slice(0, limit) .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); return { - title: item.prop('title'), - link: new URL(item.prop('href'), rootUrl).href, - pubDate: timezone(parseDate(item.find('span[title]').prop('title')), 8), + title: $item.prop('title')!, + link: new URL($item.prop('href')!, rootUrl).href, + pubDate: timezone(parseDate($item.find('span[title]').prop('title')), 8), }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const { data: detailResponse } = await got(item.link); const content = load(detailResponse); @@ -71,7 +71,7 @@ async function handler(ctx) { title: `${author} - ${subtitle}`, link: currentUrl, description: $('meta[property="og:description"]').prop('content'), - language: 'zh', + language: 'zh' as Language, subtitle, author, }; diff --git a/lib/routes/acs/journal.tsx b/lib/routes/acs/journal.tsx index 68b4b0a704..6160439ac3 100644 --- a/lib/routes/acs/journal.tsx +++ b/lib/routes/acs/journal.tsx @@ -56,28 +56,28 @@ async function handler(ctx) { const $ = load(html); - title = $('meta[property="og:title"]').attr('content'); + title = $('meta[property="og:title"]').attr('content')!; return $('.issue-item') .toArray() .map((item) => { - item = $(item); + const $item = $(item); - const a = item.find('.issue-item_title a'); - const doi = item.find('input[name="doi"]').attr('value'); + const a = $item.find('.issue-item_title a'); + const doi = $item.find('input[name="doi"]').attr('value'); return { doi, guid: doi, title: a.text(), link: `${rootUrl}${a.attr('href')}`, - pubDate: parseDate(item.find('.pub-date-value').text(), 'MMMM D, YYYY'), - author: item + pubDate: parseDate($item.find('.pub-date-value').text(), 'MMMM D, YYYY'), + author: $item .find('.issue-item_loa li') .toArray() .map((a) => $(a).text()) .join(', '), - description: renderDescription(item.find('.issue-item_img').html(), item.find('.hlFld-Abstract').html()), + description: renderDescription($item.find('.issue-item_img').html(), $item.find('.hlFld-Abstract').html()), }; }); }, diff --git a/lib/routes/adquan/case-library.ts b/lib/routes/adquan/case-library.ts index 096685cee8..6ccafb56a2 100644 --- a/lib/routes/adquan/case-library.ts +++ b/lib/routes/adquan/case-library.ts @@ -3,7 +3,7 @@ import { load } from 'cheerio'; import type { Element } from 'domhandler'; import type { Context } from 'hono'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -25,7 +25,7 @@ export const handler = async (ctx: Context): Promise => { let items: DataItem[] = $('div.article_1') .slice(0, limit) .toArray() - .map((el): Element => { + .map((el) => { const $el: Cheerio = $(el); const title: string = $el.find('p.article_2_p').text(); @@ -51,7 +51,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: upDatedStr ? parseDate(upDatedStr) : undefined, - language, + language: language as Language, }; return processedItem; @@ -65,7 +65,7 @@ export const handler = async (ctx: Context): Promise => { } return cache.tryGet(item.link, async (): Promise => { - const detailResponse = await ofetch(item.link); + const detailResponse = await ofetch(item.link!); const $$: CheerioAPI = load(detailResponse); const title: string = $$('p.infoTitle_left').text(); @@ -89,7 +89,7 @@ export const handler = async (ctx: Context): Promise => { text: description, }, updated: upDatedStr ? timezone(parseDate(upDatedStr), 8) : item.updated, - language, + language: language as Language, }; return { @@ -109,7 +109,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image: $('img.navi_logo').attr('src'), author: $('meta[name="author"]').attr('content'), - language, + language: language as Language, id: targetUrl, }; }; diff --git a/lib/routes/adquan/index.ts b/lib/routes/adquan/index.ts index a739a7cf41..ecdfd99c4d 100644 --- a/lib/routes/adquan/index.ts +++ b/lib/routes/adquan/index.ts @@ -3,7 +3,7 @@ import { load } from 'cheerio'; import type { Element } from 'domhandler'; import type { Context } from 'hono'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -25,7 +25,7 @@ export const handler = async (ctx: Context): Promise => { let items: DataItem[] = $('div.article_1') .slice(0, limit) .toArray() - .map((el): Element => { + .map((el) => { const $el: Cheerio = $(el); const title: string = $el.find('p.article_2_p').text(); @@ -51,7 +51,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: upDatedStr ? parseDate(upDatedStr) : undefined, - language, + language: language as Language, }; return processedItem; @@ -65,7 +65,7 @@ export const handler = async (ctx: Context): Promise => { } return cache.tryGet(item.link, async (): Promise => { - const detailResponse = await ofetch(item.link); + const detailResponse = await ofetch(item.link!); const $$: CheerioAPI = load(detailResponse); const title: string = $$('p.infoTitle_left').text(); @@ -89,7 +89,7 @@ export const handler = async (ctx: Context): Promise => { text: description, }, updated: upDatedStr ? timezone(parseDate(upDatedStr), 8) : item.updated, - language, + language: language as Language, }; return { @@ -109,7 +109,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image: $('img.navi_logo').attr('src'), author: $('meta[name="author"]').attr('content'), - language, + language: language as Language, id: targetUrl, }; }; diff --git a/lib/routes/aeaweb/index.tsx b/lib/routes/aeaweb/index.tsx index d3ae3a53af..80ae98c612 100644 --- a/lib/routes/aeaweb/index.tsx +++ b/lib/routes/aeaweb/index.tsx @@ -1,7 +1,7 @@ import { load } from 'cheerio'; import { renderToString } from 'hono/jsx/dom/server'; -import type { Route } from '@/types'; +import type { DataItem, Language, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -64,17 +64,18 @@ async function handler(ctx) { let items = $('h4.title a') .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); return { - link: `${rootUrl}${item.attr('href').split('&', 1)[0]}`, + title: '', + link: `${rootUrl}${$item.attr('href')!.split('&', 1)[0]}`, }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const detailResponse = await got({ method: 'get', url: item.link, @@ -85,16 +86,16 @@ async function handler(ctx) { item.doi = content('meta[name="citation_doi"]').attr('content'); item.guid = item.doi; - item.title = content('meta[name="citation_title"]').attr('content'); + item.title = content('meta[name="citation_title"]').attr('content')!; item.author = content('.author') .toArray() .map((a) => content(a).text().trim()) .join(', '); - item.pubDate = parseDate(content('meta[name="citation_publication_date"]').attr('content'), 'YYYY/MM'); + item.pubDate = parseDate(content('meta[name="citation_publication_date"]').attr('content')!, 'YYYY/MM'); item.description = renderToString( ); @@ -109,7 +110,7 @@ async function handler(ctx) { description, link: currentUrl, item: items, - language: $('html').attr('lang'), + language: $('html').attr('lang') as Language, }; } diff --git a/lib/routes/afdian/explore.ts b/lib/routes/afdian/explore.ts index 9e03ca7431..a54dc618f1 100644 --- a/lib/routes/afdian/explore.ts +++ b/lib/routes/afdian/explore.ts @@ -1,3 +1,4 @@ +import type { Route } from '@/types'; import got from '@/utils/got'; const categoryMap = { diff --git a/lib/routes/aflcio/blog.ts b/lib/routes/aflcio/blog.ts index e9570b925d..41c6562367 100644 --- a/lib/routes/aflcio/blog.ts +++ b/lib/routes/aflcio/blog.ts @@ -3,7 +3,7 @@ import { load } from 'cheerio'; import type { Element } from 'domhandler'; import type { Context } from 'hono'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -22,7 +22,7 @@ export const handler = async (ctx: Context): Promise => { let items: DataItem[] = $('article.article') .slice(0, limit) .toArray() - .map((el): Element => { + .map((el) => { const $el: Cheerio = $(el); const $aEl: Cheerio = $el.find('header.container h1 a').first(); @@ -56,7 +56,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: upDatedStr ? parseDate(upDatedStr) : undefined, - language, + language: language as Language, }; return processedItem; @@ -70,7 +70,7 @@ export const handler = async (ctx: Context): Promise => { } return cache.tryGet(item.link, async (): Promise => { - const detailResponse = await ofetch(item.link); + const detailResponse = await ofetch(item.link!); const $$: CheerioAPI = load(detailResponse); const title: string = $$('header.article-header h1').text(); @@ -101,7 +101,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: upDatedStr ? parseDate(upDatedStr) : item.updated, - language, + language: language as Language, }; return { @@ -123,7 +123,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image: $('img.main-logo').attr('src') ? new URL($('img.main-logo').attr('src') as string, baseUrl).href : undefined, author: title.split(/\|/).pop(), - language, + language: language as Language, id: targetUrl, }; }; diff --git a/lib/routes/agefans/detail.ts b/lib/routes/agefans/detail.ts index 1cd53e2c2b..d46b13e02c 100644 --- a/lib/routes/agefans/detail.ts +++ b/lib/routes/agefans/detail.ts @@ -39,11 +39,11 @@ async function handler(ctx) { .find('li') .toArray() .map((item) => { - item = $(item); - const a = item.find('a'); + const $item = $(item); + const a = $item.find('a'); return { title: a.text(), - link: a.attr('href').replace('http://', 'https://'), + link: a.attr('href')!.replace('http://', 'https://'), }; }) .toReversed(); diff --git a/lib/routes/agefans/update.ts b/lib/routes/agefans/update.ts index 6121640147..10ed4ff662 100644 --- a/lib/routes/agefans/update.ts +++ b/lib/routes/agefans/update.ts @@ -39,20 +39,20 @@ async function handler() { const list = $('.video_item') .toArray() - .map((item) => { - item = $(item); - const link = item.find('a').attr('href').replace('http://', 'https://'); + .map((item): DataItem => { + const $item = $(item); + const link = $item.find('a').attr('href')!.replace('http://', 'https://'); return { - title: item.text(), + title: $item.text(), link, - guid: `${link}#${item.find('.video_item--info').text()}`, + guid: `${link}#${$item.find('.video_item--info').text()}`, }; }); const items: DataItem[] = await pMap( list, (item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const detailResponse = await got(item.link); const content = load(detailResponse.data); diff --git a/lib/routes/agirls/topic-list.ts b/lib/routes/agirls/topic-list.ts index feeaac7988..57add56b75 100644 --- a/lib/routes/agirls/topic-list.ts +++ b/lib/routes/agirls/topic-list.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import ofetch from '@/utils/ofetch'; import { baseUrl } from './utils'; @@ -40,11 +40,11 @@ async function handler() { const items = $('.ag-topic') .toArray() .map((item) => { - item = $(item); + const $item = $(item); return { - title: item.find('.ag-topic__link').text(), - description: item.find('.ag-topic__summery').text(), - link: `${baseUrl}${item.find('.ag-topic__link').attr('href')}`, + title: $item.find('.ag-topic__link').text(), + description: $item.find('.ag-topic__summery').text(), + link: `${baseUrl}${$item.find('.ag-topic__link').attr('href')}`, }; }); @@ -53,6 +53,6 @@ async function handler() { link, description: $('head meta[name=description]').attr('content'), item: items, - language: $('html').attr('lang'), + language: $('html').attr('lang') as Language, }; } diff --git a/lib/routes/agirls/topic.ts b/lib/routes/agirls/topic.ts index d8c9ae56cf..42bf65b9d7 100644 --- a/lib/routes/agirls/topic.ts +++ b/lib/routes/agirls/topic.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -39,10 +39,10 @@ async function handler(ctx) { const list = $('.ag-post-item__link') .toArray() .map((item) => { - item = $(item); + const $item = $(item); return { - title: item.text(), - link: `${baseUrl}${item.attr('href')}`, + title: $item.text(), + link: `${baseUrl}${$item.attr('href')}`, }; }); @@ -53,6 +53,6 @@ async function handler(ctx) { link, description: ldJson['@graph'][0].description, item: items, - language: $('html').attr('lang'), + language: $('html').attr('lang') as Language, }; } diff --git a/lib/routes/agirls/z-index.ts b/lib/routes/agirls/z-index.ts index c1efd1a381..e31e4852a4 100644 --- a/lib/routes/agirls/z-index.ts +++ b/lib/routes/agirls/z-index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -43,10 +43,10 @@ async function handler(ctx) { const list = $('.ag-post-list .ag-post-item__link') .toArray() .map((item) => { - item = $(item); + const $item = $(item); return { - title: item.text(), - link: `${baseUrl}${item.attr('href')}`, + title: $item.text(), + link: `${baseUrl}${$item.attr('href')}`, }; }); @@ -57,6 +57,6 @@ async function handler(ctx) { link, description: $('head meta[name=description]').attr('content'), item: items, - language: $('html').attr('lang'), + language: $('html').attr('lang') as Language, }; } diff --git a/lib/routes/agora0/index.ts b/lib/routes/agora0/index.ts index 8863a29862..df13b039e3 100644 --- a/lib/routes/agora0/index.ts +++ b/lib/routes/agora0/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -48,18 +48,18 @@ async function handler(ctx) { let items = $('.card span:not(.comments) a') .slice(0, ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit')) : 50) .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); return { - title: item.text(), - link: item.attr('href'), + title: $item.text(), + link: $item.attr('href'), }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const detailResponse = await got({ method: 'get', url: item.link, @@ -68,7 +68,7 @@ async function handler(ctx) { const content = load(detailResponse.data); item.author = content('meta[name="author"]').attr('content'); - item.pubDate = parseDate(content('meta[property="article:published_time"]').attr('content')); + item.pubDate = parseDate(content('meta[property="article:published_time"]').attr('content')!); item.description = content('.post-content').html(); return item; diff --git a/lib/routes/agora0/pen0.ts b/lib/routes/agora0/pen0.ts index 8f65d5ee8a..a225ca8b16 100644 --- a/lib/routes/agora0/pen0.ts +++ b/lib/routes/agora0/pen0.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -37,12 +37,12 @@ async function handler() { const list = $('div article') .toArray() .slice(0, -1) // last one is a dummy - .map((item) => { - item = $(item); - const meta = item.find('h5').first().text(); + .map((item): DataItem => { + const $item = $(item); + const meta = $item.find('h5').first().text(); return { - title: item.find('h3').text(), - link: item.find('h3 a').attr('href'), + title: $item.find('h3').text(), + link: $item.find('h3 a').attr('href'), author: meta.split('|', 1)[0].trim(), pubDate: parseDate(meta.split('|', 2)[1].trim()), }; @@ -50,7 +50,7 @@ async function handler() { const items = await Promise.all( list.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const response = await got(item.link); const $ = load(response.data); $('h1').remove(); diff --git a/lib/routes/agri/index.ts b/lib/routes/agri/index.ts index de2d4248ad..ed4c3317b2 100644 --- a/lib/routes/agri/index.ts +++ b/lib/routes/agri/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Language, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -24,15 +24,15 @@ export const handler = async (ctx) => { let items = $('div.list_li_con, div.nxw_video_com') .slice(0, limit) .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); - const a = item.find('a').first(); + const a = $item.find('a').first(); const title = a.text(); - const image = item.find('img').first().prop('src') ? new URL(item.find('img').first().prop('src'), rootUrl).href : undefined; + const image = $item.find('img').first().prop('src') ? new URL($item.find('img').first().prop('src')!, rootUrl).href : undefined; const description = renderDescription({ - intro: item.find('p.con_text').text() || undefined, + intro: $item.find('p.con_text').text() || undefined, images: image ? [ { @@ -46,21 +46,21 @@ export const handler = async (ctx) => { return { title, description, - pubDate: parseDate(item.find('span.con_date_span').text() || `${item.find('div.com_time_p2').text().trim()}${item.find('div.com_time_p1').text()}`, ['YYYY-MM-DD', 'YYYY.MM.DD']), - link: new URL(a.prop('href'), currentUrl).href, + pubDate: parseDate($item.find('span.con_date_span').text() || `${$item.find('div.com_time_p2').text().trim()}${$item.find('div.com_time_p1').text()}`, ['YYYY-MM-DD', 'YYYY.MM.DD']), + link: new URL(a.prop('href')!, currentUrl).href, content: { html: description, - text: item.find('p.con_text').text() || undefined, + text: $item.find('p.con_text').text() || undefined, }, image, banner: image, - language, + language: language as Language, }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const { data: detailResponse } = await got(item.link); const $$ = load(detailResponse); @@ -78,7 +78,7 @@ export const handler = async (ctx) => { html: description, text: $$('div.content_body_box').text(), }; - item.language = language; + item.language = language as Language; item.enclosure_url = $$('div.content_body_box video').prop('src') ?? undefined; item.enclosure_type = item.enclosure_url ? 'video/mp4' : undefined; @@ -89,7 +89,7 @@ export const handler = async (ctx) => { ) ); - const image = new URL($('div.logo img').prop('src'), rootUrl).href; + const image = new URL($('div.logo img').prop('src')!, rootUrl).href; return { title: $('title').text(), @@ -97,7 +97,7 @@ export const handler = async (ctx) => { item: items, allowEmpty: true, image, - language, + language: language as Language, }; }; diff --git a/lib/routes/ahjzu/news.ts b/lib/routes/ahjzu/news.ts index 4ee5ad425f..d8749c42bc 100644 --- a/lib/routes/ahjzu/news.ts +++ b/lib/routes/ahjzu/news.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -44,15 +44,15 @@ async function handler() { const list = $('#wp_news_w9') .find('li') .toArray() - .map((item) => { - item = $(item); - const date = item.find('.column-news-date').text(); + .map((item): DataItem => { + const $item = $(item); + const date = $item.find('.column-news-date').text(); // 置顶链接自带http前缀,其他不带,需要手动判断 - const a = item.find('a').attr('href'); - const link = a.slice(0, 4) === 'http' ? a : rootUrl + a; + const a = $item.find('a').attr('href'); + const link = a!.startsWith('http') ? a : rootUrl + a; return { - title: item.find('a').attr('title'), + title: $item.find('a').attr('title')!, link, pubDate: timezone(parseDate(date), 8), }; @@ -60,7 +60,7 @@ async function handler() { const items = await Promise.all( list.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const detailResponse = await got({ method: 'get', url: item.link, diff --git a/lib/routes/aibase/daily.ts b/lib/routes/aibase/daily.ts index e3c7efcdf1..9959ef62db 100644 --- a/lib/routes/aibase/daily.ts +++ b/lib/routes/aibase/daily.ts @@ -61,7 +61,7 @@ export const route: Route = { return { title: 'AI日报', description: '每天三分钟关注AI行业趋势', - language: 'zh-cn', + language: 'zh-CN', link: 'https://www.aibase.com/zh/daily', item: items, allowEmpty: true, diff --git a/lib/routes/aibase/discover.ts b/lib/routes/aibase/discover.ts index fa413dbcc1..74e805dde5 100644 --- a/lib/routes/aibase/discover.ts +++ b/lib/routes/aibase/discover.ts @@ -63,7 +63,7 @@ export const handler = async (ctx) => { const items = processItems(apiProcs?.slice(0, limit) ?? []); - const image = new URL($('img.logo').prop('src'), rootUrl).href; + const image = new URL($('img.logo').prop('src')!, rootUrl).href; const author = $('title').text().split(/_/).pop(); diff --git a/lib/routes/aibase/news.ts b/lib/routes/aibase/news.ts index 60e8cf4446..977ae896d7 100644 --- a/lib/routes/aibase/news.ts +++ b/lib/routes/aibase/news.ts @@ -50,7 +50,7 @@ export const route: Route = { return { title: 'AI新闻资讯', description: 'AI新闻资讯 - 不错过全球AI革新的每一个时刻', - language: 'zh-cn', + language: 'zh-CN', link: 'https://www.aibase.com/zh/news', item: items, allowEmpty: true, diff --git a/lib/routes/aibase/topic.ts b/lib/routes/aibase/topic.ts index e9a445caa4..214e261d5e 100644 --- a/lib/routes/aibase/topic.ts +++ b/lib/routes/aibase/topic.ts @@ -33,7 +33,7 @@ export const handler = async (ctx) => { const items = processItems(apiTagProcs?.slice(0, limit) ?? []); - const image = new URL($('img.logo').prop('src'), rootUrl).href; + const image = new URL($('img.logo').prop('src')!, rootUrl).href; const author = $('title').text().split(/_/).pop(); diff --git a/lib/routes/aijishu/utils.ts b/lib/routes/aijishu/utils.ts index 6d4e2346d1..33fc382b91 100644 --- a/lib/routes/aijishu/utils.ts +++ b/lib/routes/aijishu/utils.ts @@ -16,7 +16,7 @@ const parseArticle = (item) => { const $ = load(resp.data); desc = $('article.fmt').html(); } catch (error) { - if (error.response.status === 403) { + if ((error as { response: { status: number } }).response.status === 403) { // skip it } else { throw error; diff --git a/lib/routes/ainvest/article.ts b/lib/routes/ainvest/article.ts index a638d3a357..e4bc563f27 100644 --- a/lib/routes/ainvest/article.ts +++ b/lib/routes/ainvest/article.ts @@ -1,5 +1,5 @@ import { fetchContentItems } from '@/routes/ainvest/utils'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; export const route: Route = { path: '/article', @@ -32,7 +32,7 @@ async function handler(ctx) { return { title: 'AInvest - Latest Articles', link: 'https://www.ainvest.com/news/articles-latest/', - language: 'en', + language: 'en' as Language, item: items, }; } diff --git a/lib/routes/ainvest/news.ts b/lib/routes/ainvest/news.ts index 8aeb08e178..4ea4f55cd9 100644 --- a/lib/routes/ainvest/news.ts +++ b/lib/routes/ainvest/news.ts @@ -1,5 +1,5 @@ import { fetchContentItems } from '@/routes/ainvest/utils'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import { ViewType } from '@/types'; export const route: Route = { @@ -35,7 +35,7 @@ async function handler(ctx) { return { title: 'AInvest - Latest News', link: 'https://www.ainvest.com/news/', - language: 'en', + language: 'en' as Language, item: items, }; } diff --git a/lib/routes/ainvest/utils.ts b/lib/routes/ainvest/utils.ts index 9c196820a0..cb7e8b5421 100644 --- a/lib/routes/ainvest/utils.ts +++ b/lib/routes/ainvest/utils.ts @@ -1,4 +1,5 @@ import { config } from '@/config'; +import type { DataItem } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; import { parseDate } from '@/utils/parse-date'; @@ -6,7 +7,7 @@ import { parseDate } from '@/utils/parse-date'; const contentStreamUrl = 'https://news.ainvest.com/news-w-ds-hxcmp-content-stream/content_stream/api/stream_item/v1/query_content_stream'; const contentPageUrl = 'https://news.ainvest.com/content-page/v1/page'; -const normalizeItem = (item) => ({ +const normalizeItem = (item): DataItem & { seoKey?: string } => ({ title: item.title, link: item.h5_url, pubDate: parseDate(item.ctime, 'X'), @@ -40,7 +41,7 @@ export const fetchContentItems = async (streamIds, limit) => { return Promise.all( list.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const response = await ofetch(`${contentPageUrl}/${item.seoKey}`); const { data } = response; diff --git a/lib/routes/aip/journal-pupp.ts b/lib/routes/aip/journal-pupp.ts index 5372bfb3d7..7a4adcd694 100644 --- a/lib/routes/aip/journal-pupp.ts +++ b/lib/routes/aip/journal-pupp.ts @@ -34,7 +34,7 @@ const handler = async (ctx) => { const authors = $(item).find('.entryAuthor.all').text(); const img = $(item).find('img').attr('src'); const link = $(item).find('.ref.nowrap').attr('href'); - const doi = link.replace('/doi/full/', ''); + const doi = link!.replace('/doi/full/', ''); const description = renderDesc(title, authors, doi, img); return { title, diff --git a/lib/routes/aip/journal.ts b/lib/routes/aip/journal.ts index f5c718e57e..8ecf94cb61 100644 --- a/lib/routes/aip/journal.ts +++ b/lib/routes/aip/journal.ts @@ -42,16 +42,16 @@ async function handler(ctx) { const { data: response } = await got.get(jrnlUrl); const $ = load(response); const jrnlName = $('meta[property="og:title"]') - .attr('content') - .match(/(?:[^=]*=)?\s*([^>]+)/)[1]; + .attr('content')! + .match(/(?:[^=]*=)?\s*([^>]+)/)![1]; const publication = $('.al-article-item-wrap.al-normal'); const list = publication.toArray().map((item) => { const title = $(item).find('.item-title a:first').text(); const link = $(item).find('.item-title a:first').attr('href'); const doilink = $(item).find('.citation-label a').attr('href'); - const doi = doilink && doilink.match(/10\.\d+\/\S+/)[0]; - const id = $(item).find('h5[data-resource-id-access]').data('resource-id-access'); + const doi = doilink && doilink.match(/10\.\d+\/\S+/)![0]; + const id = $(item).find('h5[data-resource-id-access]').data('resource-id-access') as string; const authors = $(item) .find('.al-authors-list') .find('a') diff --git a/lib/routes/airchina/index.ts b/lib/routes/airchina/index.ts index 8f92d8b5fd..f6bbf25da6 100644 --- a/lib/routes/airchina/index.ts +++ b/lib/routes/airchina/index.ts @@ -57,7 +57,7 @@ async function handler() { item.description = await cache.tryGet(detailLink, async () => { const result = await got(detailLink); const $ = load(result.data); - return $('.serviceMsg').html(); + return $('.serviceMsg').html() ?? ''; }); }) ); diff --git a/lib/routes/aisixiang/column.ts b/lib/routes/aisixiang/column.ts index a3d9607f5b..55d03bc89b 100644 --- a/lib/routes/aisixiang/column.ts +++ b/lib/routes/aisixiang/column.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; import timezone from '@/utils/timezone'; @@ -41,15 +41,15 @@ async function handler(ctx) { .slice(0, limit) .toArray() .map((item) => { - item = $(item); + const $item = $(item); - const a = item.find('a[title]'); + const a = $item.find('a[title]'); return { title: a.text(), - link: new URL(a.prop('href'), rootUrl).href, + link: new URL(a.prop('href')!, rootUrl).href, author: a.text().split(':', 1)[0], - pubDate: timezone(parseDate(item.find('span').text()), 8), + pubDate: timezone(parseDate($item.find('span').text()), 8), }; }); @@ -58,7 +58,7 @@ async function handler(ctx) { title: `爱思想 - ${title}`, link: currentUrl, description: $('div.tips').text(), - language: 'zh-cn', + language: 'zh-CN' as Language, image: new URL('images/logo.jpg', ossUrl).href, subtitle: title, }; diff --git a/lib/routes/aisixiang/thinktank.ts b/lib/routes/aisixiang/thinktank.ts index 5e27bf2350..2452385386 100644 --- a/lib/routes/aisixiang/thinktank.ts +++ b/lib/routes/aisixiang/thinktank.ts @@ -1,7 +1,7 @@ import { load } from 'cheerio'; import InvalidParameterError from '@/errors/types/invalid-parameter'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import got from '@/utils/got'; import { ossUrl, ProcessFeed, rootUrl } from './utils'; @@ -38,7 +38,7 @@ async function handler(ctx) { const title = `${$('h2').first().text()}${type}`; - let items = []; + let items: any[] = []; const targetList = $('h3') .toArray() @@ -52,11 +52,11 @@ async function handler(ctx) { } items = items.slice(0, limit).map((item) => { - item = $(item); + const $item = $(item); return { - title: item.text().split(':').pop(), - link: new URL(item.prop('href'), rootUrl).href, + title: $item.text().split(':').pop(), + link: new URL($item.prop('href')!, rootUrl).href, }; }); @@ -65,7 +65,7 @@ async function handler(ctx) { title: `爱思想 - ${title}`, link: currentUrl, description: $('div.thinktank-author-description-box p').text(), - language: 'zh-cn', + language: 'zh-CN' as Language, image: new URL('images/logo_thinktank.jpg', ossUrl).href, subtitle: title, }; diff --git a/lib/routes/aisixiang/toplist.ts b/lib/routes/aisixiang/toplist.ts index a4908ea578..990a70474a 100644 --- a/lib/routes/aisixiang/toplist.ts +++ b/lib/routes/aisixiang/toplist.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -35,15 +35,15 @@ async function handler(ctx) { .slice(0, limit) .toArray() .map((item) => { - item = $(item); + const $item = $(item); - const a = item.find('div.tips a'); + const a = $item.find('div.tips a'); return { title: a.text(), - link: new URL(a.prop('href'), rootUrl).href, - author: item.find('div.name').text(), - pubDate: parseDate(item.find('div.times').text()), + link: new URL(a.prop('href')!, rootUrl).href, + author: $item.find('div.name').text(), + pubDate: parseDate($item.find('div.times').text()), }; }); @@ -51,7 +51,7 @@ async function handler(ctx) { item: await ProcessFeed(limit, items), title: `爱思想 - ${title}`, link: currentUrl, - language: 'zh-cn', + language: 'zh-CN' as Language, image: new URL('images/logo_toplist.jpg', ossUrl).href, subtitle: title, }; diff --git a/lib/routes/aisixiang/utils.ts b/lib/routes/aisixiang/utils.ts index befc488ba6..d63f8fae13 100644 --- a/lib/routes/aisixiang/utils.ts +++ b/lib/routes/aisixiang/utils.ts @@ -29,7 +29,7 @@ const ProcessFeed = (limit, items) => .find('u') .toArray() .map((c) => content(c).text()); - item.pubDate = timezone(parseDate(content('div.info').text().split('时间:').pop()), 8); + item.pubDate = timezone(parseDate(content('div.info').text().split('时间:').pop()!), 8); item.upvotes = content('span.like-num').text() ? Number(content('span.like-num').text()) : 0; item.comments = commentMatches ? Number(commentMatches[1]) : 0; diff --git a/lib/routes/aisixiang/zhuanti.ts b/lib/routes/aisixiang/zhuanti.ts index 845c0773a7..249c0fd0e8 100644 --- a/lib/routes/aisixiang/zhuanti.ts +++ b/lib/routes/aisixiang/zhuanti.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; import timezone from '@/utils/timezone'; @@ -44,15 +44,15 @@ async function handler(ctx) { .slice(0, limit) .toArray() .map((item) => { - item = $(item); + const $item = $(item); - const a = item.find('a'); + const a = $item.find('a'); return { title: a.text(), - link: new URL(a.prop('href'), rootUrl).href, + link: new URL(a.prop('href')!, rootUrl).href, author: a.text().split(':', 1)[0], - pubDate: timezone(parseDate(item.find('span').text()), 8), + pubDate: timezone(parseDate($item.find('span').text()), 8), }; }); @@ -61,7 +61,7 @@ async function handler(ctx) { title: `爱思想 - ${title}`, link: currentUrl, description: $('div.tips p').text(), - language: 'zh-cn', + language: 'zh-CN' as Language, image: new URL('images/logo_zhuanti.jpg', ossUrl).href, subtitle: title, }; diff --git a/lib/routes/ali213/news.ts b/lib/routes/ali213/news.ts index bdb7b64428..985d5dac53 100644 --- a/lib/routes/ali213/news.ts +++ b/lib/routes/ali213/news.ts @@ -3,7 +3,7 @@ import { load } from 'cheerio'; import type { Element } from 'domhandler'; import type { Context } from 'hono'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -66,7 +66,7 @@ export const handler = async (ctx: Context): Promise => { }, image: imageSrc, banner: imageSrc, - language, + language: language as Language, }; }); @@ -79,7 +79,7 @@ export const handler = async (ctx: Context): Promise => { return cache.tryGet(item.link, async (): Promise => { try { - const detailResponse = await ofetch(item.link); + const detailResponse = await ofetch(item.link!); const $$: CheerioAPI = load(detailResponse); const title: string = $$('h1.newstit').text(); @@ -92,7 +92,7 @@ export const handler = async (ctx: Context): Promise => { mediaContent.each((_, el) => { const $$el: Cheerio = $$(el); - const pEl: Cheerio = $$el.closest('p'); + const pEl: Cheerio = $$el.closest('p') as Cheerio; const mediaUrl: string | undefined = $$el.prop('src'); const mediaType: string | undefined = mediaUrl?.split(/\./).pop(); @@ -141,7 +141,7 @@ export const handler = async (ctx: Context): Promise => { }, image, banner: image, - language, + language: language as Language, media: Object.keys(media).length > 0 ? media : undefined, _extra: { links: extraLinks.length > 0 ? extraLinks : undefined, @@ -167,7 +167,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image: feedImage, author, - language, + language: language as Language, id: targetUrl, }; }; diff --git a/lib/routes/ali213/zl.ts b/lib/routes/ali213/zl.ts index c93d750f98..7ea0074f7c 100644 --- a/lib/routes/ali213/zl.ts +++ b/lib/routes/ali213/zl.ts @@ -3,7 +3,7 @@ import { load } from 'cheerio'; import type { Element } from 'domhandler'; import type { Context } from 'hono'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -56,7 +56,7 @@ export const handler = async (ctx: Context): Promise => { }, image, banner: image, - language, + language: language as Language, }; }); @@ -68,7 +68,7 @@ export const handler = async (ctx: Context): Promise => { } return cache.tryGet(item.link, async (): Promise => { - const detailResponse = await ofetch(item.link); + const detailResponse = await ofetch(item.link!); const $$: CheerioAPI = load(detailResponse); const title: string = $$('h1.newstit').text(); @@ -131,7 +131,7 @@ export const handler = async (ctx: Context): Promise => { }, image: item.image, banner: item.image, - language, + language: language as Language, _extra: { links: extraLinks.length > 0 ? extraLinks : undefined, }, @@ -152,7 +152,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image: feedImage, author: title.split(/_/).pop(), - language, + language: language as Language, id: targetUrl, }; }; diff --git a/lib/routes/alicesoft/infomation.ts b/lib/routes/alicesoft/infomation.ts index d91c0572a2..487efc7b17 100644 --- a/lib/routes/alicesoft/infomation.ts +++ b/lib/routes/alicesoft/infomation.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Language, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; @@ -52,21 +52,21 @@ async function handler(ctx) { let items = $('div.cont-main li') .slice(0, limit) .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); return { - title: item.find('p.txt').text(), - link: item.find('a').attr('href'), - pubDate: new Date(item.find('time').attr('datetime')), + title: $item.find('p.txt').text(), + link: $item.find('a').attr('href'), + pubDate: new Date($item.find('time').attr('datetime')!), }; }); items = await Promise.all( items.map((item) => { - if (!item.link.startsWith(`${baseUrl}/information/`)) { + if (!item.link!.startsWith(`${baseUrl}/information/`)) { return item; } - return cache.tryGet(item.link, async () => { + return cache.tryGet(item.link!, async () => { const contentResponse = await got(item.link); const content = load(contentResponse.data); @@ -89,6 +89,6 @@ async function handler(ctx) { .text(), link: url, item: items, - language: 'ja', + language: 'ja' as Language, }; } diff --git a/lib/routes/alistapart/index.ts b/lib/routes/alistapart/index.ts index ded80ed7db..87901e94d6 100644 --- a/lib/routes/alistapart/index.ts +++ b/lib/routes/alistapart/index.ts @@ -1,4 +1,4 @@ -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import { getData, getList } from './utils'; @@ -32,6 +32,6 @@ async function handler() { description: 'Articles on aListApart.com', logo: 'https://i0.wp.com/alistapart.com/wp-content/uploads/2019/03/cropped-icon_navigation-laurel-512.jpg?fit=192,192&ssl=1', icon: 'https://i0.wp.com/alistapart.com/wp-content/uploads/2019/03/cropped-icon_navigation-laurel-512.jpg?fit=32,32&ssl=1', - language: 'en-us', + language: 'en-us' as Language, }; } diff --git a/lib/routes/alistapart/topic.ts b/lib/routes/alistapart/topic.ts index 350a682532..863403a387 100644 --- a/lib/routes/alistapart/topic.ts +++ b/lib/routes/alistapart/topic.ts @@ -1,4 +1,4 @@ -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import { getData, getList } from './utils'; @@ -90,6 +90,6 @@ async function handler(ctx) { description: `${topic[0].toUpperCase() + topic.slice(1)} Articles on aListApart.com`, logo: 'https://i0.wp.com/alistapart.com/wp-content/uploads/2019/03/cropped-icon_navigation-laurel-512.jpg?fit=192,192&ssl=1', icon: 'https://i0.wp.com/alistapart.com/wp-content/uploads/2019/03/cropped-icon_navigation-laurel-512.jpg?fit=32,32&ssl=1', - language: 'en-us', + language: 'en-us' as Language, }; } diff --git a/lib/routes/aliyun/database-month.ts b/lib/routes/aliyun/database-month.ts index be75ade658..e8f1633019 100644 --- a/lib/routes/aliyun/database-month.ts +++ b/lib/routes/aliyun/database-month.ts @@ -53,7 +53,7 @@ async function handler() { return cache.tryGet(link, async () => { const itemReponse = await got(link); const itemElement = load(itemReponse.data); - item.description = itemElement('.content').html(); + item.description = itemElement('.content').html() ?? ''; return item; }); }) diff --git a/lib/routes/aliyun/developer/group.ts b/lib/routes/aliyun/developer/group.ts index 60a01fbc9b..830e49f8ea 100644 --- a/lib/routes/aliyun/developer/group.ts +++ b/lib/routes/aliyun/developer/group.ts @@ -43,7 +43,7 @@ async function handler(ctx) { const $ = load(data); const title = $('div[class="header-information-title"]') .contents() - .filter((element) => element.nodeType === 3) + .filter((element: any) => element.nodeType === 3) .text() .trim(); const desc = $('div[class="header-information"]').find('span').last().text().trim(); @@ -54,13 +54,13 @@ async function handler(ctx) { link, description: desc, item: list.toArray().map((item) => { - item = $(item); - const desc = item.find('.question-desc'); - const description = item.find('.browse').text() + ' ' + desc.find('.answer').text(); + const $item = $(item); + const desc = $item.find('.question-desc'); + const description = $item.find('.browse').text() + ' ' + desc.find('.answer').text(); return { - title: item.find('.question-title').text().trim() || item.find('a p').text().trim(), - link: item.find('a').attr('href'), - pubDate: parseDate(item.find('.time').text()), + title: $item.find('.question-title').text().trim() || $item.find('a p').text().trim(), + link: $item.find('a').attr('href'), + pubDate: parseDate($item.find('.time').text()), description, }; }), diff --git a/lib/routes/aliyun/notice.ts b/lib/routes/aliyun/notice.ts index 027bf7452c..fe8753365b 100644 --- a/lib/routes/aliyun/notice.ts +++ b/lib/routes/aliyun/notice.ts @@ -53,7 +53,7 @@ async function handler(ctx) { .map((e) => { const element = $(e); const title = element.find('a').text().trim(); - const link = 'https://help.aliyun.com' + element.find('a').attr('href').trim(); + const link = 'https://help.aliyun.com' + element.find('a').attr('href')!.trim(); const date = element.find('.y-right').text(); const pubDate = timezone(parseDate(date), 8); return { @@ -69,7 +69,7 @@ async function handler(ctx) { cache.tryGet(item.link, async () => { const itemReponse = await got(item.link); const itemElement = load(itemReponse.data); - item.description = itemElement('#se-knowledge').html(); + item.description = itemElement('#se-knowledge').html() ?? ''; return item; }) diff --git a/lib/routes/aljazeera/index.tsx b/lib/routes/aljazeera/index.tsx index 5905d5fcaa..a5db835806 100644 --- a/lib/routes/aljazeera/index.tsx +++ b/lib/routes/aljazeera/index.tsx @@ -95,10 +95,10 @@ export async function handler(ctx) { : $('.u-clickable-card__link') .toArray() .map((item) => { - item = $(item); + const $item = $(item); return { - link: `${rootUrl}${item.attr('href')}`, + link: `${rootUrl}${$item.attr('href')}`, }; }); diff --git a/lib/routes/ally/rail.ts b/lib/routes/ally/rail.ts index 2d18beac54..d3b8699623 100644 --- a/lib/routes/ally/rail.ts +++ b/lib/routes/ally/rail.ts @@ -1,4 +1,5 @@ import { load } from 'cheerio'; +import type { Element } from 'domhandler'; import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; @@ -65,33 +66,33 @@ async function handler(ctx) { links = $('.left a, .container_left a').toArray(); } - let items = links + let items: DataItem[] = links .map((link) => { - link = $(link); - const url = link.attr('href'); + const $link = $(link); + const url = $link.attr('href'); const urlMatch = url && url.match(/\/html\/(\d{4})\/\w+_(\d{4})\/\d+\.html/); if (!urlMatch) { return null; } - const title = link.text(); + const title = $link.text(); return { title, link: url.startsWith('/') ? `${rootUrl}${url}` : url, pubDate: timezone(parseDate(`${urlMatch[1]}${urlMatch[2]}`), 8), }; }) - .filter(Boolean); + .filter(Boolean) as DataItem[]; const uniqueItems: DataItem[] = []; for (const item of items) { if (uniqueItems.every((uniqueItem) => uniqueItem.link !== item?.link)) { uniqueItems.push(item!); } } - items = uniqueItems.toSorted((a, b) => b.pubDate - a.pubDate).slice(0, ctx.req.query('limit') || 20); + items = uniqueItems.toSorted((a, b) => Number(b.pubDate) - Number(a.pubDate)).slice(0, ctx.req.query('limit') || 20); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const response = await got(item.link); const $ = load(response.data); // fix weird format @@ -104,7 +105,7 @@ async function handler(ctx) { .each((_, child) => { const $child = $(child); let innerHtml; - if (child.name === 'div') { + if ((child as Element).name === 'div') { innerHtml = $child.html(); innerHtml &&= innerHtml.trim(); description += !innerHtml || innerHtml === ' ' ? (description ? '
' : '') : innerHtml; @@ -115,7 +116,7 @@ async function handler(ctx) { }); } else { // http://rail.ally.net.cn/html/2022/InviteTen_0407/4686.html - description = $('div.content div').first().html(); + description = $('div.content div').first().html() ?? ''; } description = description.replace(/\s*
\s*$/, ''); // trim
at the end diff --git a/lib/routes/alwayscontrol/news.ts b/lib/routes/alwayscontrol/news.ts index 3e900aa1ed..47a1c4962c 100644 --- a/lib/routes/alwayscontrol/news.ts +++ b/lib/routes/alwayscontrol/news.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Language, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -43,7 +43,7 @@ async function handler() { // 解析新闻列表 const list = $('div.grid > a') .toArray() - .map((item) => { + .map((item): DataItem => { const $item = $(item); const image = $item.find('img').attr('src'); @@ -58,11 +58,11 @@ async function handler() { // 获取每篇新闻的详细内容 const items = await Promise.all( list.map((item) => { - if (new URL(item.link).host === 'mp.weixin.qq.com') { + if (new URL(item.link!).host === 'mp.weixin.qq.com') { return finishArticleItem({ ...item, guid: item.link }); } - return cache.tryGet(item.link, async () => { + return cache.tryGet(item.link!, async () => { const detailResponse = await got(item.link); const $detail = load(detailResponse.data); @@ -92,7 +92,7 @@ async function handler() { title: 'Always Control - 最新动态', link: listUrl, description: 'Always Control(旭衡电子)- 智能能源管理系统解决方案专家最新动态', - language: 'zh-CN', + language: 'zh-CN' as Language, item: items, image: `${baseUrl}/logo.png`, }; diff --git a/lib/routes/amazfitwatchfaces/index.ts b/lib/routes/amazfitwatchfaces/index.ts index a4a54df796..70258ed896 100644 --- a/lib/routes/amazfitwatchfaces/index.ts +++ b/lib/routes/amazfitwatchfaces/index.ts @@ -3,7 +3,7 @@ import { load } from 'cheerio'; import type { Element } from 'domhandler'; import type { Context } from 'hono'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -25,7 +25,7 @@ export const handler = async (ctx: Context): Promise => { let items: DataItem[] = $('div.wf-panel') .slice(0, limit) .toArray() - .map((el): Element => { + .map((el) => { const $el: Cheerio = $(el); const title: string = $el.prop('title'); @@ -66,7 +66,7 @@ export const handler = async (ctx: Context): Promise => { }, image, banner: image, - language, + language: language as Language, }; return processedItem; @@ -80,7 +80,7 @@ export const handler = async (ctx: Context): Promise => { } return cache.tryGet(item.link, async (): Promise => { - const detailResponse = await ofetch(item.link); + const detailResponse = await ofetch(item.link!); const $$: CheerioAPI = load(detailResponse); const title: string = $$('div.page-title h1').text(); @@ -126,7 +126,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: upDatedStr ? parseDate(upDatedStr, 'DD.MM.YYYY HH:mm') : item.updated, - language, + language: language as Language, }; return { @@ -146,7 +146,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image: $('img.mainlogolg').attr('src') ? new URL($('img.mainlogolg').attr('src') as string, baseUrl).href : undefined, author: $('meta[property="og:site_name"]').attr('content'), - language, + language: language as Language, id: targetUrl, }; }; diff --git a/lib/routes/amazon/kindle-software-updates.tsx b/lib/routes/amazon/kindle-software-updates.tsx index a26c078831..193d7a1980 100644 --- a/lib/routes/amazon/kindle-software-updates.tsx +++ b/lib/routes/amazon/kindle-software-updates.tsx @@ -46,7 +46,7 @@ async function handler() { website: `${url}?nodeId=${nodeIdValue}`, description: $(item) .find('.a-column.a-span8') - .html() + .html()! .replaceAll(/[\t\n]/g, ''), }; return data; diff --git a/lib/routes/android/platform-tools-releases.ts b/lib/routes/android/platform-tools-releases.ts index 974d49c3f9..168ca992a5 100644 --- a/lib/routes/android/platform-tools-releases.ts +++ b/lib/routes/android/platform-tools-releases.ts @@ -48,20 +48,20 @@ async function handler() { const items = $('h4') .toArray() .map((item) => { - item = $(item); + const $item = $(item); - const title = item.attr('data-text'); + const title = $item.attr('data-text'); let description = ''; - item.nextUntil('h4').each((_, el) => { + $item.nextUntil('h4').each((_, el) => { description += $(el).html(); }); return { - title, + title: title!, description, - link: `${currentUrl}#${item.attr('id')}`, - pubDate: parseDate(title.match(/\((.*)\)/)[1], 'MMMM YYYY'), + link: `${currentUrl}#${$item.attr('id')}`, + pubDate: parseDate(title!.match(/\((.*)\)/)![1], 'MMMM YYYY'), }; }); diff --git a/lib/routes/annualreviews/index.ts b/lib/routes/annualreviews/index.ts index b4a223bf6b..e499a5b705 100644 --- a/lib/routes/annualreviews/index.ts +++ b/lib/routes/annualreviews/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -51,18 +51,18 @@ async function handler(ctx) { let items = $('entry') .toArray() .map((item) => { - item = $(item); + const $item = $(item); - const doi = item.find('id').text().split('doi=').pop(); + const doi = $item.find('id').text().split('doi=').pop(); return { doi, guid: doi, - title: item.find('title').text(), - link: item.find('link').attr('href').split('?', 1)[0], - description: item.find('content').text(), - pubDate: parseDate(item.find('published').text()), - author: item + title: $item.find('title').text(), + link: $item.find('link').attr('href')!.split('?', 1)[0], + description: $item.find('content').text(), + pubDate: parseDate($item.find('published').text()), + author: $item .find('author name') .toArray() .map((a) => $(a).text()) @@ -72,7 +72,7 @@ async function handler(ctx) { items = await Promise.all( items.map((item) => - cache.tryGet(item.guid, async () => { + cache.tryGet(item.guid!, async () => { const apiUrl = `${apiRootUrl}/works/${item.doi}`; const detailResponse = await got({ @@ -95,6 +95,6 @@ async function handler(ctx) { description: $('subtitle').first().text(), link: currentUrl, item: items, - language: $('html').attr('lang'), + language: $('html').attr('lang') as Language, }; } diff --git a/lib/routes/anquanke/category.ts b/lib/routes/anquanke/category.ts index 90911962e9..107a0c09a7 100644 --- a/lib/routes/anquanke/category.ts +++ b/lib/routes/anquanke/category.ts @@ -45,7 +45,7 @@ async function handler(ctx) { ? await cache.tryGet(art_url, async () => { const { data: res } = await got(art_url); const content = load(res); - return content('#js-article').html(); + return content('#js-article').html() ?? ''; }) : item.desc, pubDate: timezone(parseDate(item.date), 8), diff --git a/lib/routes/anthropic/red.ts b/lib/routes/anthropic/red.ts index e39335e502..b48ea07ae4 100644 --- a/lib/routes/anthropic/red.ts +++ b/lib/routes/anthropic/red.ts @@ -1,7 +1,7 @@ import { load } from 'cheerio'; import pMap from 'p-map'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; import { parseDate } from '@/utils/parse-date'; @@ -29,7 +29,7 @@ async function handler() { const list = $('a[class^="note"]') .toArray() - .map((element) => { + .map((element): DataItem => { const $e = $(element); return { title: $e.find('h2, h3').text().trim(), @@ -40,8 +40,8 @@ async function handler() { const items = await pMap( list, (item) => - cache.tryGet(item.link, async () => { - const response = await ofetch(item.link); + cache.tryGet(item.link!, async () => { + const response = await ofetch(item.link!); const $ = load(response); item.pubDate = parseDate($('d-article p').first().text().trim()); diff --git a/lib/routes/anthropic/research.ts b/lib/routes/anthropic/research.ts index 9a7baa33b6..d2b630087e 100644 --- a/lib/routes/anthropic/research.ts +++ b/lib/routes/anthropic/research.ts @@ -1,7 +1,7 @@ import { load } from 'cheerio'; import pMap from 'p-map'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; import { parseDate } from '@/utils/parse-date'; @@ -70,17 +70,19 @@ async function handler() { const publicationSections = sections.filter((section) => section?.title === 'Publications'); const posts = publicationSections .flatMap((section) => section?.posts ?? []) - .map((post) => ({ - title: post.title, - link: `https://www.anthropic.com/research/${post.slug.current}`, - pubDate: parseDate(post.publishedOn), - })); + .map( + (post): DataItem => ({ + title: post.title, + link: `https://www.anthropic.com/research/${post.slug.current}`, + pubDate: parseDate(post.publishedOn), + }) + ); const items = await pMap( posts, (item) => - cache.tryGet(item.link, async () => { - const response = await ofetch(item.link); + cache.tryGet(item.link!, async () => { + const response = await ofetch(item.link!); const $ = load(response); const content = $('#main-content > article'); diff --git a/lib/routes/anytxt/release-notes.ts b/lib/routes/anytxt/release-notes.ts index e28d2a4a18..e4dafa1812 100644 --- a/lib/routes/anytxt/release-notes.ts +++ b/lib/routes/anytxt/release-notes.ts @@ -3,7 +3,7 @@ import { load } from 'cheerio'; import type { Element } from 'domhandler'; import type { Context } from 'hono'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import ofetch from '@/utils/ofetch'; import { parseDate } from '@/utils/parse-date'; @@ -23,7 +23,7 @@ export const handler = async (ctx: Context): Promise => { const items: DataItem[] = $('p.has-medium-font-size') .slice(0, limit) .toArray() - .map((el): Element => { + .map((el) => { const $el: Cheerio = $(el); const title: string = $el.text(); @@ -44,7 +44,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: upDatedStr ? parseDate(upDatedStr) : undefined, - language, + language: language as Language, }; return processedItem; @@ -59,7 +59,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image, author: $('meta[property="og:site_name"]').attr('content'), - language, + language: language as Language, id: $('meta[property="og:url"]').attr('content'), }; }; diff --git a/lib/routes/apache/apisix/blog.ts b/lib/routes/apache/apisix/blog.ts index 8bf1d32742..43eed0377f 100644 --- a/lib/routes/apache/apisix/blog.ts +++ b/lib/routes/apache/apisix/blog.ts @@ -15,7 +15,7 @@ async function getArticles() { title: a.find('h2').text(), description: a.find('p').text(), link: a.attr('href'), - pubDate: parseDate($(elem).find('footer').find('time').attr('datetime')), + pubDate: parseDate($(elem).find('footer').find('time').attr('datetime')!), category: $(elem) .find('header div a') .toArray() diff --git a/lib/routes/apkpure/versions.ts b/lib/routes/apkpure/versions.ts index 93f2e5b6db..e03afa5f18 100644 --- a/lib/routes/apkpure/versions.ts +++ b/lib/routes/apkpure/versions.ts @@ -43,19 +43,19 @@ async function handler(ctx) { await context.close(); const $ = load(r); - const img = new URL($('.ver-top img').attr('src')); + const img = new URL($('.ver-top img').attr('src')!); img.searchParams.delete('w'); // get full resolution icon const items = $('.ver li') .toArray() .map((ver) => { - ver = $(ver); + const $ver = $(ver); return { - title: ver.find('.ver-item-n').text(), - description: ver.html(), - link: `${baseUrl}${ver.find('a').attr('href')}`, + title: $ver.find('.ver-item-n').text(), + description: $ver.html(), + link: `${baseUrl}${$ver.find('a').attr('href')}`, pubDate: parseDate( - ver + $ver .find('.update-on') .text() .replaceAll(/年|月/g, '-') diff --git a/lib/routes/apnews/mobile-api.ts b/lib/routes/apnews/mobile-api.ts index 7263daa9dc..64260ffdf0 100644 --- a/lib/routes/apnews/mobile-api.ts +++ b/lib/routes/apnews/mobile-api.ts @@ -84,7 +84,7 @@ async function handler(ctx) { return; }) .filter(Boolean) - .toSorted((a, b) => b.pubDate - a.pubDate) + .toSorted((a, b) => Number(b!.pubDate) - Number(a!.pubDate)) .slice(0, ctx.req.query('limit') ? Number(ctx.req.query('limit')) : 20); const items = ctx.req.query('fulltext') === 'true' ? await pMap(list, (item) => fetchArticle(item), { concurrency: 10 }) : list; diff --git a/lib/routes/apnews/rss.ts b/lib/routes/apnews/rss.ts index 8a2889422a..8c10b14280 100644 --- a/lib/routes/apnews/rss.ts +++ b/lib/routes/apnews/rss.ts @@ -1,4 +1,4 @@ -import type { Route } from '@/types'; +import type { Data, Route } from '@/types'; import { ViewType } from '@/types'; import parser from '@/utils/rss-parser'; @@ -46,5 +46,5 @@ async function handler(ctx) { return { ...res, item: items, - }; + } as unknown as Data; } diff --git a/lib/routes/apnews/sitemap.ts b/lib/routes/apnews/sitemap.ts index 3d61a0c0af..9e443a2bdc 100644 --- a/lib/routes/apnews/sitemap.ts +++ b/lib/routes/apnews/sitemap.ts @@ -1,7 +1,7 @@ import { load } from 'cheerio'; import pMap from 'p-map'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import { ViewType } from '@/types'; import ofetch from '@/utils/ofetch'; import { parseDate } from '@/utils/parse-date'; @@ -67,7 +67,7 @@ async function handler(ctx) { .find(String.raw`news\:language`) .text() ); - let res = { link: $(e).find('loc').text() }; + let res: DataItem & { link: string; lastmod?: Date } = { link: $(e).find('loc').text(), title: '' }; if (title) { res = Object.assign(res, { title }); } @@ -83,7 +83,7 @@ async function handler(ctx) { return res; }) .filter((e) => Boolean(e.link) && !new URL(e.link).pathname.split('/').includes('hub')) - .toSorted((a, b) => (a.pubDate && b.pubDate ? b.pubDate - a.pubDate : b.lastmod - a.lastmod)) + .toSorted((a, b) => (a.pubDate && b.pubDate ? Number(b.pubDate) - Number(a.pubDate) : Number(b.lastmod) - Number(a.lastmod))) .slice(0, ctx.req.query('limit') ? Number(ctx.req.query('limit')) : 20); const items = ctx.req.query('fulltext') === 'true' ? await pMap(list, (item) => fetchArticle(item), { concurrency: 20 }) : list; diff --git a/lib/routes/apnews/topics.ts b/lib/routes/apnews/topics.ts index cdb8eeb919..4e35540e21 100644 --- a/lib/routes/apnews/topics.ts +++ b/lib/routes/apnews/topics.ts @@ -1,7 +1,7 @@ import { load } from 'cheerio'; import pMap from 'p-map'; -import type { Route } from '@/types'; +import type { DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import got from '@/utils/got'; @@ -61,7 +61,7 @@ async function handler(ctx) { title: $('title').text(), description: $("meta[property='og:description']").text(), link: url, - item: removeDuplicateByKey(items, 'link'), - language: $('html').attr('lang'), + item: removeDuplicateByKey(items, 'link') as DataItem[], + language: $('html').attr('lang') as Language, }; } diff --git a/lib/routes/apnic/index.ts b/lib/routes/apnic/index.ts index fcf98adb86..8f0b6db312 100644 --- a/lib/routes/apnic/index.ts +++ b/lib/routes/apnic/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -25,7 +25,7 @@ async function handler() { // 从 RSS XML 中直接提取文章信息 const list = $('item') .toArray() - .map((item) => { + .map((item): DataItem => { const $item = $(item); return { title: $item.find('title').text(), @@ -42,7 +42,7 @@ async function handler() { const items = await Promise.all( list.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const { data: articleData } = await got(item.link); const $article = load(articleData); diff --git a/lib/routes/app-sales/index.ts b/lib/routes/app-sales/index.ts index ffbc99d8f2..d8ffb40968 100644 --- a/lib/routes/app-sales/index.ts +++ b/lib/routes/app-sales/index.ts @@ -2,7 +2,7 @@ import type { CheerioAPI } from 'cheerio'; import { load } from 'cheerio'; import type { Context } from 'hono'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import ofetch from '@/utils/ofetch'; @@ -35,7 +35,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image: $('a.brand-logo img').attr('src') ? new URL($('a.brand-logo img').attr('src') as string, baseUrl).href : undefined, author: title.split(/\|/).pop(), - language, + language: language as Language, id: targetUrl, }; }; diff --git a/lib/routes/app-sales/mostwanted.ts b/lib/routes/app-sales/mostwanted.ts index 90ea983392..4f0932d309 100644 --- a/lib/routes/app-sales/mostwanted.ts +++ b/lib/routes/app-sales/mostwanted.ts @@ -2,7 +2,7 @@ import type { CheerioAPI } from 'cheerio'; import { load } from 'cheerio'; import type { Context } from 'hono'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import ofetch from '@/utils/ofetch'; @@ -36,7 +36,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image: $('a.brand-logo img').attr('src') ? new URL($('a.brand-logo img').attr('src') as string, baseUrl).href : undefined, author: title.split(/\|/).pop(), - language, + language: language as Language, id: targetUrl, }; }; diff --git a/lib/routes/app-sales/util.tsx b/lib/routes/app-sales/util.tsx index 4f5c2e08ce..a508a5dbb8 100644 --- a/lib/routes/app-sales/util.tsx +++ b/lib/routes/app-sales/util.tsx @@ -135,7 +135,7 @@ const processItems = ($: CheerioAPI, selector: string): DataItem[] => $(selector) .toArray() .map((el) => { - const $el: Cheerio = $(el); + const $el = $(el) as Cheerio; const appName: string = $el.find('p.app-name').text()?.trim(); const appDev: string = $el.find('p.app-dev').text()?.trim(); diff --git a/lib/routes/apple/apps.ts b/lib/routes/apple/apps.ts index cf854838fb..d0f4b20146 100644 --- a/lib/routes/apple/apps.ts +++ b/lib/routes/apple/apps.ts @@ -1,4 +1,4 @@ -import type { DataItem, Route } from '@/types'; +import type { Route } from '@/types'; import { ViewType } from '@/types'; import ofetch from '@/utils/ofetch'; import { parseDate } from '@/utils/parse-date'; @@ -113,7 +113,7 @@ async function handler(ctx) { const artistName = attributes.artistName; const platformAttributes = attributes.platformAttributes; - let items: DataItem[] = []; + let items: any[] = []; let title: string; let description = ''; let image = ''; @@ -129,7 +129,7 @@ async function handler(ctx) { image = platformAttribute.iconArtwork?.url?.replace('{w}x{h}{c}.{f}', '3000x3000bb.webp'); } else { title = appName; - for (const [pid, platformAttribute] of Object.entries(platformAttributes)) { + for (const [pid, platformAttribute] of Object.entries(platformAttributes)) { items = [ ...items, ...platformAttribute.versionHistory.map((v) => ({ diff --git a/lib/routes/apple/exchange-repair.ts b/lib/routes/apple/exchange-repair.ts index 1f879c470e..64d595a11b 100644 --- a/lib/routes/apple/exchange-repair.ts +++ b/lib/routes/apple/exchange-repair.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -39,19 +39,19 @@ async function handler(ctx) { const $ = load(response.data); const list = $('section.as-container-column') .toArray() - .map((item) => { - item = $(item); - const a = item.find('.icon-chevronright').parent(); + .map((item): DataItem => { + const $item = $(item); + const a = $item.find('.icon-chevronright').parent(); return { title: a.text(), - link: new URL(a.attr('href'), host).href, - pubDate: parseDate(item.find('.note').text(), ['MMMM D, YYYY', 'D MMMM YYYY', 'YYYY 年 M 月 D 日']), + link: new URL(a.attr('href')!, host).href, + pubDate: parseDate($item.find('.note').text(), ['MMMM D, YYYY', 'D MMMM YYYY', 'YYYY 年 M 月 D 日']), }; }); const out = await Promise.all( list.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const response = await got(item.link); const $$ = load(response.data); diff --git a/lib/routes/apple/newsroom.ts b/lib/routes/apple/newsroom.ts index 949b2dce19..958314dc12 100644 --- a/lib/routes/apple/newsroom.ts +++ b/lib/routes/apple/newsroom.ts @@ -2,7 +2,7 @@ import type { CheerioAPI } from 'cheerio'; import { load } from 'cheerio'; import type { Item } from 'rss-parser'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import { ViewType } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -31,7 +31,7 @@ const extractArticleDescription = ($: CheerioAPI) => { return article.html() ?? undefined; }; -const fetchArticle = (item: Item & { link: string }) => +const fetchArticle = (item: Item & { link: string; author?: string }) => cache.tryGet(item.link, async () => { const response = await ofetch(item.link); const $ = load(response); @@ -72,7 +72,7 @@ async function handler(ctx) { feedLink: feedUrl, description: 'Apple 新闻中心是 Apple 新闻的来源。阅读新闻稿、获取最新消息、观看视频和下载图片。', item: items, - language: 'zh-CN', + language: 'zh-CN' as Language, }; } diff --git a/lib/routes/apple/podcast.ts b/lib/routes/apple/podcast.ts index ffaaaeec0e..2e5adc9d36 100644 --- a/lib/routes/apple/podcast.ts +++ b/lib/routes/apple/podcast.ts @@ -50,7 +50,7 @@ async function handler(ctx) { const bearerToken = await cache.tryGet( 'apple:podcast:bearer', async () => { - const moduleAddress = new URL($('head script[type="module"]').attr('src'), baseUrl).href; + const moduleAddress = new URL($('head script[type="module"]').attr('src')!, baseUrl).href; const modulesResponse = await ofetch(moduleAddress, { parseResponse: (txt) => txt, }); diff --git a/lib/routes/apple/security-releases.ts b/lib/routes/apple/security-releases.ts index 54f5330653..1ebf493fea 100644 --- a/lib/routes/apple/security-releases.ts +++ b/lib/routes/apple/security-releases.ts @@ -3,7 +3,7 @@ import { load } from 'cheerio'; import type { Element } from 'domhandler'; import type { Context } from 'hono'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -30,7 +30,7 @@ export const handler = async (ctx: Context): Promise => { let items: DataItem[] = $trEls .slice(1, limit) .toArray() - .map((el): Element => { + .map((el) => { const $el: Cheerio = $(el); const titleEl: Cheerio = $el.find('td').first(); @@ -58,7 +58,7 @@ export const handler = async (ctx: Context): Promise => { text: description, }, updated: upDatedStr ? parseDate(upDatedStr, ['DD MMM YYYY', 'YYYY 年 MM 月 DD 日']) : undefined, - language, + language: language as Language, }; return processedItem; @@ -71,7 +71,7 @@ export const handler = async (ctx: Context): Promise => { } return cache.tryGet(item.link, async (): Promise => { - const detailResponse = await ofetch(item.link); + const detailResponse = await ofetch(item.link!); const $$: CheerioAPI = load(detailResponse); const title: string = item.title ?? $$('h1.gb-header').text(); @@ -81,7 +81,7 @@ export const handler = async (ctx: Context): Promise => { const description: string | undefined = item.description + renderDescription({ - description: $$('div#sections').html(), + description: $$('div#sections').html() ?? undefined, }); const pubDateStr: string | undefined = detailResponse.match(/publish_date:\s"(\d{8})",/, '')?.[1]; const authors: DataItem['author'] = $$('meta[property="og:site_name"]').attr('content'); @@ -97,7 +97,7 @@ export const handler = async (ctx: Context): Promise => { text: description, }, updated: upDatedStr ? parseDate(upDatedStr, 'MMDDYYYY') : item.updated, - language, + language: language as Language, }; return { @@ -115,7 +115,7 @@ export const handler = async (ctx: Context): Promise => { item: items, allowEmpty: true, author: $('meta[property="og:site_name"]').attr('content'), - language, + language: language as Language, id: targetUrl, }; }; diff --git a/lib/routes/appleinsider/index.ts b/lib/routes/appleinsider/index.ts index 227b4c299d..518bb0bc6e 100644 --- a/lib/routes/appleinsider/index.ts +++ b/lib/routes/appleinsider/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -48,18 +48,18 @@ async function handler(ctx) { let items = $(`${category === '' ? '#news-river ' : ''}.river`) .slice(0, ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit')) : 30) .toArray() - .map((item) => { - item = $(item).find('a').first(); + .map((item): DataItem => { + const $item = $(item).find('a').first(); return { - title: item.text(), - link: item.attr('href'), + title: $item.text(), + link: $item.attr('href'), }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const detailResponse = await got({ method: 'get', url: item.link, @@ -73,7 +73,7 @@ async function handler(ctx) { item.title = content('.h1-adjust').text(); item.author = content('.avatar-link a').attr('title'); - item.pubDate = parseDate(content('time').first().attr('datetime')); + item.pubDate = parseDate(content('time').first().attr('datetime')!); item.description = content('header').next('.row').html(); return item; diff --git a/lib/routes/appstore/price.ts b/lib/routes/appstore/price.ts index 829df08ea3..aba710ac68 100644 --- a/lib/routes/appstore/price.ts +++ b/lib/routes/appstore/price.ts @@ -59,7 +59,7 @@ async function handler(ctx) { result = res.data.results.macapps; } - const item = []; + const item: any[] = []; const title = `${country === 'cn' ? '限免提醒' : 'Price watcher'}: ${result.title} for ${type === 'macapps' ? 'macOS' : 'iOS'}`; diff --git a/lib/routes/appstorrent/programs.tsx b/lib/routes/appstorrent/programs.tsx index 009ca2d296..2a9b1cda04 100644 --- a/lib/routes/appstorrent/programs.tsx +++ b/lib/routes/appstorrent/programs.tsx @@ -5,7 +5,6 @@ import { renderToString } from 'hono/jsx/dom/server'; import type { Data, DataItem, Route } from '@/types'; import cache from '@/utils/cache'; -import type { Options } from '@/utils/got'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -23,7 +22,7 @@ async function handler(ctx?: Context): Promise { const limit = ctx?.req.query('limit') ? Number.parseInt(ctx?.req.query('limit') ?? '20') : 20; const baseUrl = 'https://appstorrent.ru'; const currentUrl = `${baseUrl}/programs/`; - const gotOptions: Options = { + const gotOptions: Parameters[1] = { http2: true, }; diff --git a/lib/routes/aqara/news.ts b/lib/routes/aqara/news.ts index e28bfe468d..4a5ea99f47 100644 --- a/lib/routes/aqara/news.ts +++ b/lib/routes/aqara/news.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -49,14 +49,14 @@ async function handler(ctx) { ) ); - const icon = $('link[rel="shortcut icon"]').prop('href').split('?', 1)[0]; + const icon = $('link[rel="shortcut icon"]').prop('href')!.split('?', 1)[0]; return { item: items, title: $('title').text(), link: currentUrl, description: $('meta[name="description"]').prop('content'), - language: 'zh-cn', + language: 'zh-CN' as Language, image: $('meta[property="og:image"]').prop('content'), icon, logo: icon, diff --git a/lib/routes/aqara/post.tsx b/lib/routes/aqara/post.tsx index bcdc2aeab7..b69c7ebc0f 100644 --- a/lib/routes/aqara/post.tsx +++ b/lib/routes/aqara/post.tsx @@ -1,7 +1,7 @@ import { load } from 'cheerio'; import { renderToString } from 'hono/jsx/dom/server'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -99,7 +99,7 @@ async function handler(ctx) { title: `${title}${filterName ? ` - ${filterName}` : ''}`, link: currentUrl, description: $('meta[property="og:title"]').prop('content'), - language: $('meta[property="og:locale"]').prop('content'), + language: $('meta[property="og:locale"]').prop('content') as Language, image: $('meta[name="msapplication-TileImage"]').prop('content'), icon, logo: icon, diff --git a/lib/routes/aqara/region.ts b/lib/routes/aqara/region.ts index d8954d3c94..d130d9e3b8 100644 --- a/lib/routes/aqara/region.ts +++ b/lib/routes/aqara/region.ts @@ -28,5 +28,5 @@ function handler(ctx) { const { region = 'en', type = 'news' } = ctx.req.param(); const redirectTo = `/aqara/${region}/category/${types[type]}`; - ctx.set('redirect', redirectTo); + return ctx.set('redirect', redirectTo); } diff --git a/lib/routes/aqicn/aqi.ts b/lib/routes/aqicn/aqi.ts index 6f07c3e636..e6e8217b1d 100644 --- a/lib/routes/aqicn/aqi.ts +++ b/lib/routes/aqicn/aqi.ts @@ -19,22 +19,20 @@ export const route: Route = { maintainers: ['ladeng07'], handler, url: 'aqicn.org', - descriptions: ` -| 参数 | 污染成分 | -| -------- | -------- | -| pm25 | PM2.5 | -| pm10 | PM10 | -| o3 | O3 | -| no2 | NO2 | -| so2 | SO2 | -| co | CO | + description: `| 参数 | 污染成分 | +| ---- | -------- | +| pm25 | PM2.5 | +| pm10 | PM10 | +| o3 | O3 | +| no2 | NO2 | +| so2 | SO2 | +| co | CO | -举例: [https://rsshub.app/aqicn/beijing/pm25,pm10](https://rsshub.app/aqicn/beijing/pm25,pm10) +举例: -1. 显示单个污染成分,例如「pm25」, [https://rsshub.app/aqicn/beijing/pm25](https://rsshub.app/aqicn/beijing/pm25) -2. 逗号分隔显示多个污染成分,例如「pm25,pm10」,[https://rsshub.app/aqicn/beijing/pm25,pm10](https://rsshub.app/aqicn/beijing/pm25,pm10) -3. 城市子站 ID 获取方法:右键显示网页源代码,搜索 "idx" (带双冒号),后面的 ID 就是子站的 ID,如你给的链接 ID 是 4258,RSS 地址就是 [https://rsshub.app/aqicn/4258](https://rsshub.app/aqicn/4258) -`, +1. 显示单个污染成分,例如「pm25」, +2. 逗号分隔显示多个污染成分,例如「pm25,pm10」, +3. 城市子站 ID 获取方法:右键显示网页源代码,搜索 "idx" (带双冒号),后面的 ID 就是子站的 ID,如你给的链接 ID 是 4258,RSS 地址就是 `, }; async function handler(ctx) { diff --git a/lib/routes/arcteryx/regear-new-arrivals.tsx b/lib/routes/arcteryx/regear-new-arrivals.tsx index bd6b4773ea..06e7c3e3e1 100644 --- a/lib/routes/arcteryx/regear-new-arrivals.tsx +++ b/lib/routes/arcteryx/regear-new-arrivals.tsx @@ -43,7 +43,7 @@ async function handler() { const $ = load(data); const contents = $('script:contains("window.__PRELOADED_STATE__")').text(); const regex = /\{.*\}/; - let items = JSON.parse(contents.match(regex)[0]).shop.items; + let items = JSON.parse(contents.match(regex)![0]).shop.items; items = items.filter((item) => item.availableSizes.length !== 0); const list = items.map((item) => { diff --git a/lib/routes/arcteryx/utils.ts b/lib/routes/arcteryx/utils.ts index 13cbda2296..2342802265 100644 --- a/lib/routes/arcteryx/utils.ts +++ b/lib/routes/arcteryx/utils.ts @@ -1,7 +1,7 @@ function generateRssData(item, index, arr, country) { const attributeSet = new Set(['name', 'image', 'short_description', 'slug', `price_${country}`, `discount_price_${country}`]); const attributes = item.attribute; - const data = {}; + const data = {} as Record; for (const attribute of attributes) { const key = attribute.name; diff --git a/lib/routes/aschmelyun/blog.ts b/lib/routes/aschmelyun/blog.ts index 0a2b43cbbe..6b78722256 100644 --- a/lib/routes/aschmelyun/blog.ts +++ b/lib/routes/aschmelyun/blog.ts @@ -26,17 +26,17 @@ async function handler() { const items = $('div.rounded-lg') .toArray() .map((item) => { - item = $(item); - const a = item.find('a.text-xl').first(); + const $item = $(item); + const a = $item.find('a.text-xl').first(); return { title: a.text(), - link: new URL(a.attr('href'), 'https://aschmelyun.com/blog/').href, - pubDate: parseDate(item.find('span.text-sm').text()), - category: item + link: new URL(a.attr('href')!, 'https://aschmelyun.com/blog/').href, + pubDate: parseDate($item.find('span.text-sm').text()), + category: $item .find('a.rounded-full') .toArray() .map((cat) => $(cat).text().trim()), - description: item.find('p').first().text(), + description: $item.find('p').first().text(), }; }); diff --git a/lib/routes/asiafruitchina/categories.ts b/lib/routes/asiafruitchina/categories.ts index 15367ada38..f16283e6ce 100644 --- a/lib/routes/asiafruitchina/categories.ts +++ b/lib/routes/asiafruitchina/categories.ts @@ -3,7 +3,7 @@ import { load } from 'cheerio'; import type { Element } from 'domhandler'; import type { Context } from 'hono'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -25,7 +25,7 @@ export const handler = async (ctx: Context): Promise => { let items: DataItem[] = $('div.listBlocks ul li') .slice(0, limit) .toArray() - .map((el): Element => { + .map((el) => { const $el: Cheerio = $(el); const $aEl: Cheerio = $el.find('div.storyDetails h3 a'); @@ -63,7 +63,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: upDatedStr ? parseDate(upDatedStr) : undefined, - language, + language: language as Language, }; return processedItem; @@ -77,7 +77,7 @@ export const handler = async (ctx: Context): Promise => { } return cache.tryGet(item.link, async (): Promise => { - const detailResponse = await ofetch(item.link); + const detailResponse = await ofetch(item.link!); const $$: CheerioAPI = load(detailResponse); const title: string = $$('div.story_title h1').text(); @@ -104,7 +104,7 @@ export const handler = async (ctx: Context): Promise => { text: description, }, updated: upDatedStr ? parseDate(upDatedStr) : item.updated, - language, + language: language as Language, }; const extraLinkEls: Element[] = $$('div.extrasStory ul li').toArray(); @@ -148,7 +148,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image: $('img.logo').attr('src'), author: title.split(/-/).pop(), - language, + language: language as Language, id: targetUrl, }; }; diff --git a/lib/routes/asiafruitchina/news.ts b/lib/routes/asiafruitchina/news.ts index 94a2477ac8..ff2fa1c66d 100644 --- a/lib/routes/asiafruitchina/news.ts +++ b/lib/routes/asiafruitchina/news.ts @@ -3,7 +3,7 @@ import { load } from 'cheerio'; import type { Element } from 'domhandler'; import type { Context } from 'hono'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -24,7 +24,7 @@ export const handler = async (ctx: Context): Promise => { let items: DataItem[] = $('div.listBlocks ul li') .slice(0, limit) .toArray() - .map((el): Element => { + .map((el) => { const $el: Cheerio = $(el); const $aEl: Cheerio = $el.find('div.storyDetails h3 a'); @@ -62,7 +62,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: upDatedStr ? parseDate(upDatedStr) : undefined, - language, + language: language as Language, }; return processedItem; @@ -76,7 +76,7 @@ export const handler = async (ctx: Context): Promise => { } return cache.tryGet(item.link, async (): Promise => { - const detailResponse = await ofetch(item.link); + const detailResponse = await ofetch(item.link!); const $$: CheerioAPI = load(detailResponse); const title: string = $$('div.story_title h1').text(); @@ -103,7 +103,7 @@ export const handler = async (ctx: Context): Promise => { text: description, }, updated: upDatedStr ? parseDate(upDatedStr) : item.updated, - language, + language: language as Language, }; const extraLinkEls: Element[] = $$('div.extrasStory ul li').toArray(); @@ -147,7 +147,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image: $('img.logo').attr('src'), author: title.split(/-/).pop(), - language, + language: language as Language, id: targetUrl, }; }; diff --git a/lib/routes/asiantolick/index.ts b/lib/routes/asiantolick/index.ts index d9996974d2..9df0f2b37e 100644 --- a/lib/routes/asiantolick/index.ts +++ b/lib/routes/asiantolick/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Language, Route } from '@/types'; import cache from '@/utils/cache'; import { getSubPath } from '@/utils/common-utils'; import got from '@/utils/got'; @@ -35,7 +35,7 @@ export async function handler(ctx) { const apiUrl = new URL('ajax/buscar_posts.php', rootUrl).href; const currentUrl = new URL(category.replace(/^(tag|category)?\/(\d+)/, '$1-$2'), rootUrl).href; - const searchParams = {}; + const searchParams: Record = {}; const matches = category.match(/^(tag|category|search|page)?[/-]?(\w+)/); if (matches) { @@ -53,14 +53,14 @@ export async function handler(ctx) { let items = $('a.miniatura') .slice(0, limit) .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); - const image = item.find('div.background_miniatura img'); + const image = $item.find('div.background_miniatura img'); return { - title: item.find('div.base_tt').text(), - link: item.prop('href'), + title: $item.find('div.base_tt').text(), + link: $item.prop('href'), description: renderDescription({ images: image ? [ @@ -71,25 +71,25 @@ export async function handler(ctx) { ] : undefined, }), - author: item.find('.author').text(), - category: item + author: $item.find('.author').text(), + category: $item .find('.category') .toArray() .map((c) => $(c).text()), - guid: image ? image.prop('post-id') : item.link.match(/\/(\d+)/)[1], + guid: image ? image.prop('post-id') : ($item as any).link.match(/\/(\d+)/)[1], }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const { data: detailResponse } = await got(item.link); const content = load(detailResponse); item.title = content('h1').text(); item.description = renderDescription({ - description: content('#metadata_qrcode').html(), + description: content('#metadata_qrcode').html() ?? undefined, images: content('div.miniatura') .toArray() .map((i) => ({ @@ -124,7 +124,7 @@ export async function handler(ctx) { title: title === 'Asian To Lick' ? title : `Asian To Lick - ${title}`, link: currentUrl, description: $('meta[property="og:description"]').prop('content'), - language: $('html').prop('lang'), + language: $('html').prop('lang') as Language, image: $('meta[name="msapplication-TileImage"]').prop('content'), icon, logo: icon, diff --git a/lib/routes/asus/gpu-tweak.ts b/lib/routes/asus/gpu-tweak.ts index 75e87aad69..188143de8f 100644 --- a/lib/routes/asus/gpu-tweak.ts +++ b/lib/routes/asus/gpu-tweak.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -37,22 +37,22 @@ async function handler() { const items = $('section div.inner div.item') .toArray() .map((item) => { - item = $(item); - item.find('.last').remove(); + const $item = $(item); + $item.find('.last').remove(); return { - title: item.find('.ver h6').text().trim(), - description: item.find('.btnbox a.open_patch_lightbox').attr('data-info'), - pubDate: parseDate(item.find('.ti').text()), - link: item.find('.btnbox a[download=]').attr('href'), + title: $item.find('.ver h6').text().trim(), + description: $item.find('.btnbox a.open_patch_lightbox').attr('data-info'), + pubDate: parseDate($item.find('.ti').text()), + link: $item.find('.btnbox a[download=]').attr('href'), }; }); return { title: $('head title').text(), description: $('meta[name=description]').attr('content'), - image: new URL($('head link[rel="shortcut icon"]').attr('href'), pageUrl).href, + image: new URL($('head link[rel="shortcut icon"]').attr('href')!, pageUrl).href, link: pageUrl, item: items, - language: $('html').attr('lang'), + language: $('html').attr('lang') as Language, }; } diff --git a/lib/routes/atcoder/contest.ts b/lib/routes/atcoder/contest.ts index bba128343b..1201752bca 100644 --- a/lib/routes/atcoder/contest.ts +++ b/lib/routes/atcoder/contest.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -68,18 +68,18 @@ async function handler(ctx) { .find('tr') .slice(1, ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit')) : 20) .toArray() - .map((item) => { - item = $(item).find('td a').eq(1); + .map((item): DataItem => { + const $item = $(item).find('td a').eq(1); return { - title: item.text(), - link: `${rootUrl}${item.attr('href')}?lang=${language}`, + title: $item.text(), + link: `${rootUrl}${$item.attr('href')}?lang=${language}`, }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const detailResponse = await got({ method: 'get', url: item.link, diff --git a/lib/routes/atcoder/post.ts b/lib/routes/atcoder/post.ts index 18e2ff9379..b8d545eaa5 100644 --- a/lib/routes/atcoder/post.ts +++ b/lib/routes/atcoder/post.ts @@ -40,13 +40,13 @@ async function handler(ctx) { const items = $('.panel') .toArray() .map((item) => { - item = $(item); + const $item = $(item); return { - title: item.find('.panel-title').text(), - description: item.find('.panel-body').html(), - link: `${rootUrl}${item.find('.panel-title a').attr('href')}`, - pubDate: timezone(parseDate(item.find('.timeago').attr('datetime')), 9), + title: $item.find('.panel-title').text(), + description: $item.find('.panel-body').html(), + link: `${rootUrl}${$item.find('.panel-title a').attr('href')}`, + pubDate: timezone(parseDate($item.find('.timeago').attr('datetime')!), 9), }; }); diff --git a/lib/routes/augmentcode/blog.tsx b/lib/routes/augmentcode/blog.tsx index a0cfba8c5c..1dcf7c76f3 100644 --- a/lib/routes/augmentcode/blog.tsx +++ b/lib/routes/augmentcode/blog.tsx @@ -5,7 +5,7 @@ import type { Context } from 'hono'; import { raw } from 'hono/html'; import { renderToString } from 'hono/jsx/dom/server'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -43,7 +43,7 @@ export const handler = async (ctx: Context): Promise => { let items: DataItem[] = $('div[data-slot="card"]') .slice(0, limit) .toArray() - .map((el): Element => { + .map((el) => { const $el: Cheerio = $(el); const title: string = $el.find('div[data-slot="card-content"]').text(); @@ -70,7 +70,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: upDatedStr ? parseDate(upDatedStr) : undefined, - language, + language: language as Language, }; return processedItem; @@ -83,7 +83,7 @@ export const handler = async (ctx: Context): Promise => { } return cache.tryGet(item.link, async (): Promise => { - const detailResponse = await ofetch(item.link); + const detailResponse = await ofetch(item.link!); const $$: CheerioAPI = load(detailResponse); const title: string = $$('article h1').text(); @@ -105,7 +105,7 @@ export const handler = async (ctx: Context): Promise => { const $$authorEl: Cheerio = $$(authorEl); return { - name: $$authorEl.attr('content'), + name: $$authorEl.attr('content')!, url: undefined, avatar: undefined, }; @@ -124,7 +124,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: upDatedStr ? parseDate(upDatedStr) : item.updated, - language, + language: language as Language, }; return { @@ -145,7 +145,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image: $('meta[property="og:image"]').attr('content'), author: title.split(/-/).pop()?.trim(), - language, + language: language as Language, id: targetUrl, }; }; diff --git a/lib/routes/auto-stats/index.ts b/lib/routes/auto-stats/index.ts index dd9b81d8e8..2ae24337af 100644 --- a/lib/routes/auto-stats/index.ts +++ b/lib/routes/auto-stats/index.ts @@ -1,7 +1,7 @@ import { load } from 'cheerio'; import iconv from 'iconv-lite'; -import type { Route } from '@/types'; +import type { DataItem, Language, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -44,22 +44,22 @@ async function handler(ctx) { let items = $('a.dnews font') .slice(0, limit) .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); - const title = item.text(); + const title = $item.text(); const pubDate = title.match(/(\d{4}(?:\/\d{1,2}){2}\s\d{1,2}(?::\d{2}){2})/)?.[1] ?? undefined; return { title: title.replace(/●/, '').split(/(\d+/, 1)[0], - link: new URL(item.parent().prop('href'), rootUrl).href, - pubDate: timezone(parseDate(pubDate, 'YYYY/M/D H:mm:ss'), 8), + link: new URL($item.parent().prop('href')!, rootUrl).href, + pubDate: timezone(parseDate(pubDate!, 'YYYY/M/D H:mm:ss'), 8), }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const { data: detailResponse } = await got(item.link, { responseType: 'buffer', }); @@ -84,7 +84,7 @@ async function handler(ctx) { title: $('title').text(), link: currentUrl, description: subtitle, - language: 'zh', + language: 'zh' as Language, image, subtitle, allowEmpty: true, diff --git a/lib/routes/azul/packages.ts b/lib/routes/azul/packages.ts index 8a29eb08a8..55a204c411 100644 --- a/lib/routes/azul/packages.ts +++ b/lib/routes/azul/packages.ts @@ -2,7 +2,7 @@ import type { CheerioAPI } from 'cheerio'; import { load } from 'cheerio'; import type { Context } from 'hono'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import ofetch from '@/utils/ofetch'; @@ -44,7 +44,7 @@ export const handler = async (ctx: Context): Promise => { category: categories, guid, id: guid, - language, + language: language as Language, }; const enclosureUrl: string | undefined = item.download_url; @@ -72,7 +72,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image: $('meta[property="og:image"]').attr('content'), author: $('meta[property="og:site_name"]').attr('content'), - language, + language: language as Language, id: $('meta[property="og:url"]').attr('content'), }; }; diff --git a/lib/routes/azurlane/news.ts b/lib/routes/azurlane/news.ts index a0b38daab7..6b824a1772 100644 --- a/lib/routes/azurlane/news.ts +++ b/lib/routes/azurlane/news.ts @@ -59,7 +59,7 @@ const ja: Route['handler'] = async (ctx) => { return { title: `アズールレーン - ${JP[type]}`, link: 'https://www.azurlane.jp/news', - language: 'ja-JP', + language: 'ja', image: 'https://play-lh.googleusercontent.com/9QTLYD2_Jd6OIKHwRHkEBnFAgPmVKJwf2xmHjzPk-5w0SRLZumsCoQZGlO8d_kB3Gdld=w480-h960-rw', icon: 'https://play-lh.googleusercontent.com/9QTLYD2_Jd6OIKHwRHkEBnFAgPmVKJwf2xmHjzPk-5w0SRLZumsCoQZGlO8d_kB3Gdld=w480-h960-rw', logo: 'https://play-lh.googleusercontent.com/9QTLYD2_Jd6OIKHwRHkEBnFAgPmVKJwf2xmHjzPk-5w0SRLZumsCoQZGlO8d_kB3Gdld=w480-h960-rw', diff --git a/lib/routes/backlinko/blog.ts b/lib/routes/backlinko/blog.ts index a90fe1bde0..e9699991a8 100644 --- a/lib/routes/backlinko/blog.ts +++ b/lib/routes/backlinko/blog.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Language, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -40,7 +40,7 @@ async function handler() { props: { pageProps }, } = nextData; - const posts = [...pageProps.posts.nodes, ...pageProps.backlinkoLockedPosts.nodes].map((post) => ({ + const posts = [...pageProps.posts.nodes, ...pageProps.backlinkoLockedPosts.nodes].map((post): DataItem & { apiUrl: string } => ({ title: post.title, link: `${baseUrl}/${post.slug}`, pubDate: parseDate(post.modified), @@ -50,7 +50,7 @@ async function handler() { const items = await Promise.all( posts.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const { data } = await got(item.apiUrl); const post = data.pageProps.post || data.pageProps.lockedPost; @@ -65,7 +65,7 @@ async function handler() { title: pageProps.page.seo.title, description: pageProps.page.seo.metaDesc, link, - language: 'en', + language: 'en' as Language, item: items, }; } diff --git a/lib/routes/bad/index.ts b/lib/routes/bad/index.ts index ac4654c4d1..169a966433 100644 --- a/lib/routes/bad/index.ts +++ b/lib/routes/bad/index.ts @@ -35,18 +35,18 @@ async function handler(ctx) { const items = $('.entry') .toArray() .map((item) => { - item = $(item); + const $item = $(item); - const a = item.find('a.title'); + const a = $item.find('a.title'); - item.find('img').each((_, el) => { + $item.find('img').each((_, el) => { $(el).attr('src', $(el).attr('data-echo')); $(el).removeClass('lazy'); $(el).removeAttr('data-echo'); $(el).removeAttr('id'); }); - item.find('video').each((_, el) => { + $item.find('video').each((_, el) => { $(el).attr('poster', $(el).attr('data-echo')); $(el).removeAttr('data-echo'); $(el).removeAttr('onerror'); @@ -56,10 +56,10 @@ async function handler(ctx) { return { title: a.text(), link: a.attr('href'), - description: item.find('.coverdiv').html(), - author: item.find('.author').text().trim(), - pubDate: timezone(parseDate(item.find('time').attr('datetime')), 8), - category: item + description: $item.find('.coverdiv').html(), + author: $item.find('.author').text().trim(), + pubDate: timezone(parseDate($item.find('time').attr('datetime')!), 8), + category: $item .find('.label') .toArray() .map((l) => $(l).text().trim()), diff --git a/lib/routes/baidu/search.tsx b/lib/routes/baidu/search.tsx index 72beec7aa1..9238e56560 100644 --- a/lib/routes/baidu/search.tsx +++ b/lib/routes/baidu/search.tsx @@ -3,7 +3,7 @@ import { raw } from 'hono/html'; import { renderToString } from 'hono/jsx/dom/server'; import { config } from '@/config'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; @@ -79,6 +79,6 @@ async function handler(ctx) { title: `${keyword} - 百度搜索`, description: `${keyword} - 百度搜索`, link: url, - item: items, + item: items as DataItem[], }; } diff --git a/lib/routes/baidu/tieba/post.tsx b/lib/routes/baidu/tieba/post.tsx index e3b1b89cb8..975dd947e6 100644 --- a/lib/routes/baidu/tieba/post.tsx +++ b/lib/routes/baidu/tieba/post.tsx @@ -67,7 +67,7 @@ async function handler(ctx) { const html = await getPost(id, lz); const $ = load(html); - const title = $('.pb-title-wrap .pb-title').text().trim() || ''; + const title = $('.pb-title-wrap .pb-title').text().trim(); // 使用新的 Vue 渲染页面选择器 - 只选择 virtual-list-item 避免重复 const list = $('.virtual-list-item'); diff --git a/lib/routes/baidu/top.tsx b/lib/routes/baidu/top.tsx index f62471298d..9c0c915982 100644 --- a/lib/routes/baidu/top.tsx +++ b/lib/routes/baidu/top.tsx @@ -1,4 +1,5 @@ import { load } from 'cheerio'; +import type { Comment } from 'domhandler'; import { renderToString } from 'hono/jsx/dom/server'; import type { Route } from '@/types'; @@ -53,12 +54,15 @@ async function handler(ctx) { const $ = load(response); - const { data } = JSON.parse( - $('#sanRoot') - .contents() - .filter((e) => e.nodeType === 8) - .prevObject[0].data.match(/s-data:(.*)/)[1] - ); + const sDataMatch = $('#sanRoot') + .contents() + .toArray() + .find((e): e is Comment => e.nodeType === 8) + ?.data.match(/s-data:(.*)/); + if (!sDataMatch) { + throw new Error('Unable to find s-data in page'); + } + const { data } = JSON.parse(sDataMatch[1]); const items = data.cards[0].content.map((item) => ({ title: item.word, diff --git a/lib/routes/bakamh/manga.ts b/lib/routes/bakamh/manga.ts index 3bad01f2f8..17abe20cd5 100644 --- a/lib/routes/bakamh/manga.ts +++ b/lib/routes/bakamh/manga.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; import { parseDate } from '@/utils/parse-date'; @@ -18,7 +18,7 @@ const handler = async (ctx) => { const list = $('li.wp-manga-chapter') .toArray() .slice(0, limit) - .map((item) => { + .map((item): DataItem => { const $item = $(item); const itemDate = $item.find('i').text().replaceAll(' ', ''); @@ -36,14 +36,14 @@ const handler = async (ctx) => { const items = await Promise.all( list.map((item) => - cache.tryGet(item.link, async () => { - const response = await ofetch(item.link); + cache.tryGet(item.link!, async () => { + const response = await ofetch(item.link!); const $ = load(response); const comicpage = $('div.reading-content img'); const containerDiv = $('
'); comicpage.appendTo(containerDiv); item.description = containerDiv.html(); - item.pubDate = parseDate(item.pubDate, 'YYYY年M月D日'); + item.pubDate = parseDate(item.pubDate!, 'YYYY年M月D日'); return item; }) ) diff --git a/lib/routes/bandcamp/live.ts b/lib/routes/bandcamp/live.ts index 03024db9f3..876f8cc57e 100644 --- a/lib/routes/bandcamp/live.ts +++ b/lib/routes/bandcamp/live.ts @@ -43,18 +43,18 @@ async function handler() { const items = $('.live-listing') .toArray() .map((item) => { - item = $(item); + const $item = $(item); return { - link: item.find('.title-link').attr('href'), - title: item.find('.show-title').text(), - author: item.find('.show-artist').text(), - pubDate: parseDate(item.find('.show-time-container').text().trim().split(' UTC', 1)[0]), + link: $item.find('.title-link').attr('href'), + title: $item.find('.show-title').text(), + author: $item.find('.show-artist').text(), + pubDate: parseDate($item.find('.show-time-container').text().trim().split(' UTC', 1)[0]), description: ``, }; }); diff --git a/lib/routes/bandcamp/tag.ts b/lib/routes/bandcamp/tag.ts index 1cd069a3d3..8f142a4037 100644 --- a/lib/routes/bandcamp/tag.ts +++ b/lib/routes/bandcamp/tag.ts @@ -58,7 +58,7 @@ async function handler(ctx) { item.title = content('.trackTitle').eq(0).text(); item.author = content('h3 span a').text(); - item.description = content('#tralbumArt').html() + content('#trackInfo').html(); + item.description = content('#tralbumArt').html()! + content('#trackInfo').html()!; return item; }) diff --git a/lib/routes/bandisoft/history.ts b/lib/routes/bandisoft/history.ts index e931d079c6..a2d81fd9a0 100644 --- a/lib/routes/bandisoft/history.ts +++ b/lib/routes/bandisoft/history.ts @@ -3,7 +3,7 @@ import { load } from 'cheerio'; import type { Element } from 'domhandler'; import type { Context } from 'hono'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import ofetch from '@/utils/ofetch'; import { parseDate } from '@/utils/parse-date'; @@ -153,7 +153,7 @@ export const handler = async (ctx: Context): Promise => { const items: DataItem[] = $('div.row') .slice(0, limit) .toArray() - .map((el): Element => { + .map((el) => { const $el: Cheerio = $(el); const version: string | undefined = $el.find('div.cell1').text(); @@ -179,7 +179,7 @@ export const handler = async (ctx: Context): Promise => { text: description, }, updated: upDatedStr ? parseDate(upDatedStr) : undefined, - language: lang, + language: lang as Language, }; return processedItem; @@ -193,7 +193,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image: $('img#logo_light').attr('src'), author, - language: lang, + language: lang as Language, id: targetUrl, }; }; diff --git a/lib/routes/bangumi.tv/calendar/today.tsx b/lib/routes/bangumi.tv/calendar/today.tsx index f329bf89e2..21382de7e1 100644 --- a/lib/routes/bangumi.tv/calendar/today.tsx +++ b/lib/routes/bangumi.tv/calendar/today.tsx @@ -88,7 +88,7 @@ async function handler() { guid: id, title: [ bgm.title, - Object.values(bgm.titleTranslate) + Object.values(bgm.titleTranslate) .map((t) => t.join('|')) .join('|'), ] diff --git a/lib/routes/bangumi.tv/group/reply.ts b/lib/routes/bangumi.tv/group/reply.ts index b235bfbb56..445946a1a9 100644 --- a/lib/routes/bangumi.tv/group/reply.ts +++ b/lib/routes/bangumi.tv/group/reply.ts @@ -57,7 +57,7 @@ async function handler(ctx) { date: $el.children().first().find('small').children().remove().end().text().slice(3), }; }); - const finalLatestReplies = [...latestReplies, ...latestSubReplies].toSorted((a, b) => b.id.localeCompare(a.id)); + const finalLatestReplies = [...latestReplies, ...latestSubReplies].toSorted((a, b) => b.id!.localeCompare(a.id!)); const postTopic = { title, diff --git a/lib/routes/bangumi.tv/group/topic.ts b/lib/routes/bangumi.tv/group/topic.ts index 3b135a7987..27b3bee632 100644 --- a/lib/routes/bangumi.tv/group/topic.ts +++ b/lib/routes/bangumi.tv/group/topic.ts @@ -41,7 +41,7 @@ async function handler(ctx) { $('.topic_list .topic') .toArray() .map((elem) => { - const link = new URL($('.subject a', elem).attr('href'), baseUrl).href; + const link = new URL($('.subject a', elem).attr('href')!, baseUrl).href; return cache.tryGet(link, async () => { const html = await ofetch(link); const $ = load(html); @@ -49,7 +49,7 @@ async function handler(ctx) { const summary = 'Reply: ' + $('.posts', elem).text(); return { link, - title: $('.subject a', elem).attr('title'), + title: $('.subject a', elem).attr('title')!, pubDate: parseDate($('.lastpost .time', elem).text()), description: fullText ? summary + '

' + fullText : summary, author: $('.author a', elem).text(), diff --git a/lib/routes/bangumi.tv/subject/comments.ts b/lib/routes/bangumi.tv/subject/comments.ts index aa325f0062..7a8454b060 100644 --- a/lib/routes/bangumi.tv/subject/comments.ts +++ b/lib/routes/bangumi.tv/subject/comments.ts @@ -14,9 +14,9 @@ export const getComments = async (subjectID, minLength) => { .map((el) => { const $el = $(el); const $rateEl = $el.find('.starlight'); - let rate = null; + let rate: string | null = null; if ($rateEl.length > 0) { - rate = $rateEl.attr('class').match(/stars(\d)/)[1]; + rate = $rateEl.attr('class')!.match(/stars(\d)/)![1]; } const dateString = $el.find('small.grey').text().slice(2); diff --git a/lib/routes/bangumi.tv/user/blog.ts b/lib/routes/bangumi.tv/user/blog.ts index c96c32a56b..299c7bcd35 100644 --- a/lib/routes/bangumi.tv/user/blog.ts +++ b/lib/routes/bangumi.tv/user/blog.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; import { parseDate } from '@/utils/parse-date'; @@ -39,20 +39,20 @@ async function handler(ctx) { const list = $('#entry_list div.item') .find('h2.title') .toArray() - .map((item) => { - item = $(item); - const a = item.find('a'); + .map((item): DataItem => { + const $item = $(item); + const a = $item.find('a'); return { title: a.text(), - link: new URL(a.attr('href'), 'https://bgm.tv').href, - pubDate: timezone(parseDate(item.parent().find('small.time').text()), 0), + link: new URL(a.attr('href')!, 'https://bgm.tv').href, + pubDate: timezone(parseDate($item.parent().find('small.time').text()), 0), }; }); const items = await Promise.all( list.map((item) => - cache.tryGet(item.link, async () => { - const res = await ofetch(item.link); + cache.tryGet(item.link!, async () => { + const res = await ofetch(item.link!); const content = load(res); item.description = content('#entry_content').html(); diff --git a/lib/routes/banshujiang/index.ts b/lib/routes/banshujiang/index.ts index 8da9a402f5..4b27553337 100644 --- a/lib/routes/banshujiang/index.ts +++ b/lib/routes/banshujiang/index.ts @@ -3,7 +3,7 @@ import { load } from 'cheerio'; import type { Element } from 'domhandler'; import type { Context } from 'hono'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -25,7 +25,7 @@ export const handler = async (ctx: Context): Promise => { let items: DataItem[] = $('ul.small-list li.row') .slice(0, limit) .toArray() - .map((el): Element => { + .map((el) => { const $el: Cheerio = $(el); const $aEl: Cheerio = $el.find('span.book-property__title').first().next('a'); @@ -40,7 +40,7 @@ export const handler = async (ctx: Context): Promise => { }, ] : undefined, - description: $el.find('div.small-list__item-desc').html(), + description: $el.find('div.small-list__item-desc').html() ?? undefined, }); const pubDateStr: string | undefined = image?.split(/\?timestamp=/).pop(); const linkUrl: string | undefined = $aEl.attr('href'); @@ -63,7 +63,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: upDatedStr ? parseDate(upDatedStr, 'x') : undefined, - language, + language: language as Language, }; return processedItem; @@ -76,7 +76,7 @@ export const handler = async (ctx: Context): Promise => { } return cache.tryGet(item.link, async (): Promise => { - const detailResponse = await ofetch(item.link); + const detailResponse = await ofetch(item.link!); const $$: CheerioAPI = load(detailResponse); const title: string = $$('div.ebook-title').text().trim(); @@ -122,7 +122,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: upDatedStr ? parseDate(upDatedStr, 'x') : item.updated, - language, + language: language as Language, }; return { @@ -145,7 +145,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image: new URL('logo.png?imageView2/2/w/128/h/128/q/100', baseUrl).href, author: $('a.brand').text(), - language, + language: language as Language, id: $('meta[property="og:url"]').attr('content'), }; }; diff --git a/lib/routes/banyuetan/index.ts b/lib/routes/banyuetan/index.ts index b8055ebb80..b864cf574c 100644 --- a/lib/routes/banyuetan/index.ts +++ b/lib/routes/banyuetan/index.ts @@ -3,7 +3,7 @@ import { load } from 'cheerio'; import type { Element } from 'domhandler'; import type { Context } from 'hono'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -26,7 +26,7 @@ export const handler = async (ctx: Context): Promise => { let items: DataItem[] = $('div.bty_tbtj_list ul.clearFix li') .slice(0, limit) .toArray() - .map((el): Element => { + .map((el) => { const $el: Cheerio = $(el); const $aEl: Cheerio = $el.find('h3 a'); @@ -59,7 +59,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: upDatedStr ? parseDate(upDatedStr) : undefined, - language, + language: language as Language, }; return processedItem; @@ -72,7 +72,7 @@ export const handler = async (ctx: Context): Promise => { } return cache.tryGet(item.link, async (): Promise => { - const detailResponse = await ofetch(item.link); + const detailResponse = await ofetch(item.link!); const $$: CheerioAPI = load(detailResponse); const title: string = $$('div.detail_tit h1').text(); @@ -88,7 +88,7 @@ export const handler = async (ctx: Context): Promise => { const $$authorEl: Cheerio = $$(authorEl); return { - name: $$authorEl.attr('content'), + name: $$authorEl.attr('content')!, url: undefined, avatar: undefined, }; @@ -109,7 +109,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: upDatedStr ? timezone(parseDate(upDatedStr), 8) : item.updated, - language, + language: language as Language, }; return { @@ -130,7 +130,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image: new URL('static/v1/image/logo.png', baseUrl).href, author: title.split(/—/).pop(), - language, + language: language as Language, id: targetUrl, }; }; diff --git a/lib/routes/baobua/category.ts b/lib/routes/baobua/category.ts index a764c987db..c59fc8ea24 100644 --- a/lib/routes/baobua/category.ts +++ b/lib/routes/baobua/category.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; @@ -43,7 +43,7 @@ async function handler(ctx) { return { title: `${SUB_NAME_PREFIX} - Category: ${category}`, link: url, - item: await Promise.all( + item: (await Promise.all( itemRaw .map((e) => { const item = $(e); @@ -57,6 +57,6 @@ async function handler(ctx) { return cache.tryGet(link, () => loadArticle(link)); }) .filter(Boolean) - ), + )) as DataItem[], }; } diff --git a/lib/routes/baobua/latest.ts b/lib/routes/baobua/latest.ts index 23fed0300e..259d52d347 100644 --- a/lib/routes/baobua/latest.ts +++ b/lib/routes/baobua/latest.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; @@ -40,7 +40,7 @@ async function handler() { return { title: `${SUB_NAME_PREFIX} - Latest`, link: SUB_URL, - item: await Promise.all( + item: (await Promise.all( itemRaw .map((e) => { const item = $(e); @@ -54,6 +54,6 @@ async function handler() { return cache.tryGet(link, () => loadArticle(link)); }) .filter(Boolean) - ), + )) as DataItem[], }; } diff --git a/lib/routes/baobua/search.ts b/lib/routes/baobua/search.ts index 29dd7ac0a3..cf3669e18c 100644 --- a/lib/routes/baobua/search.ts +++ b/lib/routes/baobua/search.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; @@ -56,7 +56,7 @@ async function handler(ctx) { } return cache.tryGet(link, () => loadArticle(link)); }) - .filter(Boolean) + .filter(Boolean) as Array> ), }; } diff --git a/lib/routes/baozimh/index.tsx b/lib/routes/baozimh/index.tsx index 7e1b2aa28f..fb59dc7d23 100644 --- a/lib/routes/baozimh/index.tsx +++ b/lib/routes/baozimh/index.tsx @@ -1,7 +1,7 @@ import { load } from 'cheerio'; import { renderToString } from 'hono/jsx/dom/server'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; @@ -41,7 +41,7 @@ async function handler(ctx) { .first() .children() .toArray() - .map((item) => { + .map((item): DataItem => { const title = $(item).find('span').text(); const link = rootUrl + $(item).find('a').attr('href'); @@ -56,7 +56,7 @@ async function handler(ctx) { .first() .children() .toArray() - .map((item) => { + .map((item): DataItem => { const title = $(item).find('span').text(); const link = rootUrl + $(item).find('a').attr('href'); @@ -71,7 +71,7 @@ async function handler(ctx) { const items = await Promise.all( combinedList.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const detailResponse = await got(item.link); const $ = load(detailResponse.data); item.description = renderToString( diff --git a/lib/routes/barronschina/index.ts b/lib/routes/barronschina/index.ts index 8005332270..b477b94a13 100644 --- a/lib/routes/barronschina/index.ts +++ b/lib/routes/barronschina/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -51,15 +51,15 @@ async function handler(ctx) { ? await Promise.all( $('.title') .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); return { - title: item.find('.title').text(), - link: `${rootUrl}${item.parent().attr('href')}`, + title: $item.find('.title').text(), + link: `${rootUrl}${$item.parent().attr('href')}`, }; }) .map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const detailResponse = await got({ method: 'get', url: item.link, @@ -77,19 +77,19 @@ async function handler(ctx) { : $('dd') .toArray() .map((item) => { - item = $(item); + const $item = $(item); - const title = item.find('strong').text(); - item.find('strong').remove(); + const title = $item.find('strong').text(); + $item.find('strong').remove(); - const description = item.find('.short').html(); - item.find('.short').remove(); + const description = $item.find('.short').html(); + $item.find('.short').remove(); return { title, description, link: currentUrl, - pubDate: timezone(parseDate(`${item.parent().find('dt').text()} ${item.text()}`), 8), + pubDate: timezone(parseDate(`${$item.parent().find('dt').text()} ${$item.text()}`), 8), }; }); diff --git a/lib/routes/bast/index.ts b/lib/routes/bast/index.ts index 462a956730..f84608ff38 100644 --- a/lib/routes/bast/index.ts +++ b/lib/routes/bast/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -56,19 +56,19 @@ async function handler(ctx) { let items = selection .slice(0, limit) .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); return { - title: item.text().trim(), - link: item.attr('href'), + title: $item.text().trim(), + link: $item.attr('href'), }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { - if (/bast\.net\.cn/.test(item.link)) { + cache.tryGet(item.link!, async () => { + if (/bast\.net\.cn/.test(item.link!)) { const detailResponse = await got({ method: 'get', url: item.link, @@ -76,10 +76,10 @@ async function handler(ctx) { const content = load(detailResponse.data); - item.title = content('meta[name="ArticleTitle"]').attr('content'); + item.title = content('meta[name="ArticleTitle"]').attr('content')!; item.author = content('meta[name="contentSource"]').attr('content'); - item.pubDate = timezone(parseDate(content('meta[name="pubdate"]').attr('content')), 8); - item.category = [content('meta[name="ColumnName"]').attr('content')]; + item.pubDate = timezone(parseDate(content('meta[name="pubdate"]').attr('content')!), 8); + item.category = [content('meta[name="ColumnName"]').attr('content')!]; item.description = content('.arccont').html(); } diff --git a/lib/routes/bbc/sport.ts b/lib/routes/bbc/sport.ts index 92ecda00eb..42e35156ec 100644 --- a/lib/routes/bbc/sport.ts +++ b/lib/routes/bbc/sport.ts @@ -34,7 +34,7 @@ async function handler(ctx) { const initialData = extractInitialData($); const { page } = initialData.stores.metadata; - const list: DataItem[] = Object.values(initialData.data) + const list: DataItem[] = Object.values(initialData.data) .filter((d) => d.name === 'hierarchical-promo-collection' && d.props.title !== 'Elsewhere on the BBC') .flatMap((d) => d.data.promos) .map((item) => ({ diff --git a/lib/routes/bbc/utils.tsx b/lib/routes/bbc/utils.tsx index a298262cfb..065e103f59 100644 --- a/lib/routes/bbc/utils.tsx +++ b/lib/routes/bbc/utils.tsx @@ -376,7 +376,7 @@ const extractArticleWithInitialData = ($: CheerioAPI, item) => { }; } - const article = Object.values(initialData.data).find((d) => d.name === 'article')?.data; + const article = Object.values(initialData.data).find((d) => d.name === 'article')?.data; const topics = Array.isArray(article?.topics) ? article.topics : []; const blocks = article?.content?.model?.blocks; diff --git a/lib/routes/bbcnewslabs/news.ts b/lib/routes/bbcnewslabs/news.ts index 267d5efdf9..c6a511036b 100644 --- a/lib/routes/bbcnewslabs/news.ts +++ b/lib/routes/bbcnewslabs/news.ts @@ -40,12 +40,12 @@ async function handler() { const items = $('a[href^="/news/20"]') .toArray() .map((item) => { - item = $(item); + const $item = $(item); return { - title: item.find('h3[class^="thumbnail-module--thumbnailTitle--"]').text(), - description: item.find('span[class^="thumbnail-module--thumbnailDescription--"]').text(), - pubDate: parseDate(item.find('span[class^="thumbnail-module--thumbnailType--"]').text()), - link: rootUrl + item.attr('href'), + title: $item.find('h3[class^="thumbnail-module--thumbnailTitle--"]').text(), + description: $item.find('span[class^="thumbnail-module--thumbnailDescription--"]').text(), + pubDate: parseDate($item.find('span[class^="thumbnail-module--thumbnailType--"]').text()), + link: rootUrl + $item.attr('href'), }; }); diff --git a/lib/routes/bc3ts/list.tsx b/lib/routes/bc3ts/list.tsx index 586b83e0d4..5125b41937 100644 --- a/lib/routes/bc3ts/list.tsx +++ b/lib/routes/bc3ts/list.tsx @@ -1,7 +1,7 @@ import { renderToString } from 'hono/jsx/dom/server'; import { config } from '@/config'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import ofetch from '@/utils/ofetch'; import { parseDate } from '@/utils/parse-date'; @@ -76,7 +76,7 @@ async function handler(ctx) { return { title: `爆料公社${sort === '1' ? '最新' : '熱門'}動態`, link: baseUrl, - language: 'zh-TW', + language: 'zh-TW' as Language, image: 'https://img.bc3ts.net/image/web/main/logo-white-new-2023.png', icon: 'https://img.bc3ts.net/image/web/main/logo/logo_icon_6th_2024_192x192.png', item: items, diff --git a/lib/routes/bdys/index.tsx b/lib/routes/bdys/index.tsx index 2e910f432c..6ab829381f 100644 --- a/lib/routes/bdys/index.tsx +++ b/lib/routes/bdys/index.tsx @@ -5,7 +5,7 @@ import pMap from 'p-map'; import { config } from '@/config'; import ConfigNotFoundError from '@/errors/types/config-not-found'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -123,11 +123,11 @@ async function handler(ctx) { const list = $('.card-body .card a') .slice(0, 15) .toArray() - .map((item) => { - item = $(item); - const link = item.attr('href').split(';jsessionid='); + .map((item): DataItem => { + const $item = $(item); + const link = $item.attr('href')!.split(';jsessionid='); jsessionid = link[1]; - const next = item.next(); + const next = $item.next(); return { title: next.find('h3').text(), link: `${rootUrl}${link[0]}`, @@ -142,7 +142,7 @@ async function handler(ctx) { const items = await pMap( list, (item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const detailResponse = await got({ method: 'get', url: item.link, @@ -150,7 +150,7 @@ async function handler(ctx) { }); const downloadResponse = await got({ method: 'get', - url: `${rootUrl}/downloadInfo/list?mid=${item.link.split('/', 5)[4].split('.', 1)[0]}`, + url: `${rootUrl}/downloadInfo/list?mid=${item.link!.split('/', 5)[4].split('.', 1)[0]}`, headers, }); const content = load(detailResponse.data); diff --git a/lib/routes/beijingprice/index.ts b/lib/routes/beijingprice/index.ts index 0422acc019..b4a24e5697 100644 --- a/lib/routes/beijingprice/index.ts +++ b/lib/routes/beijingprice/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Language, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -21,10 +21,10 @@ export const handler = async (ctx) => { let items = $('div.jgzx.rightcontent ul li') .slice(0, limit) .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); - const a = item.find('a'); + const a = $item.find('a'); const link = a.prop('href'); const msg = a.prop('msg'); @@ -41,9 +41,9 @@ export const handler = async (ctx) => { return { title, - pubDate: parseDate(item.contents().last().text()), - link: enclosureUrl ?? (link.startsWith('http') ? link : new URL(link, rootUrl).href), - language, + pubDate: parseDate($item.contents().last().text()), + link: enclosureUrl ?? (link!.startsWith('http') ? link : new URL(link!, rootUrl).href), + language: language as Language, enclosure_url: enclosureUrl, enclosure_type: enclosureType, enclosure_title: enclosureUrl ? title : undefined, @@ -52,8 +52,8 @@ export const handler = async (ctx) => { items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { - if (!item.link.includes('www.beijingprice.cn') || item.link.endsWith('.pdf')) { + cache.tryGet(item.link!, async () => { + if (!item.link!.includes('www.beijingprice.cn') || item.link!.endsWith('.pdf')) { return item; } @@ -79,14 +79,14 @@ export const handler = async (ctx) => { html: description, text: $$('div.news-content').text(), }; - item.language = language; + item.language = language as Language; return item; }) ) ); - const image = new URL($('a.header-logo img').prop('src'), rootUrl).href; + const image = new URL($('a.header-logo img').prop('src')!, rootUrl).href; return { title: $('title').text(), @@ -96,7 +96,7 @@ export const handler = async (ctx) => { allowEmpty: true, image, author: $('meta[name="keywords"]').prop('content'), - language, + language: language as Language, }; }; diff --git a/lib/routes/bendibao/news.ts b/lib/routes/bendibao/news.ts index aa0f41606f..ad035d2d56 100644 --- a/lib/routes/bendibao/news.ts +++ b/lib/routes/bendibao/news.ts @@ -1,7 +1,7 @@ import { load } from 'cheerio'; import InvalidParameterError from '@/errors/types/invalid-parameter'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -63,14 +63,14 @@ async function handler(ctx) { let items = $('ul.focus-news li') .toArray() - .map((item) => { - item = $(item).find('a'); + .map((item): DataItem => { + const $item = $(item).find('a'); - const link = item.attr('href'); + const link = $item.attr('href'); return { - title: item.text(), - link: link.indexOf('http') === 0 ? link : `${rootUrl}${link}`, + title: $item.text(), + link: link!.startsWith('http') ? link : `${rootUrl}${link}`, }; }); @@ -91,21 +91,21 @@ async function handler(ctx) { items = $('#listNewsTimeLy div.info') .toArray() - .map((item) => { - item = $(item).find('a'); + .map((item): DataItem => { + const $item = $(item).find('a'); - const link = item.attr('href'); + const link = $item.attr('href'); return { - title: item.text(), - link: link.indexOf('http') === 0 ? link : `${rootUrl}${link}`, + title: $item.text(), + link: link!.startsWith('http') ? link : `${rootUrl}${link}`, }; }); } - items = await Promise.all( + items = (await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { try { const detailResponse = await got({ method: 'get', @@ -137,7 +137,7 @@ async function handler(ctx) { } }) ) - ); + )) as typeof items; return { title, diff --git a/lib/routes/bilibili/bangumi.ts b/lib/routes/bilibili/bangumi.ts index 49369c150b..5ec26b7b45 100644 --- a/lib/routes/bilibili/bangumi.ts +++ b/lib/routes/bilibili/bangumi.ts @@ -44,7 +44,7 @@ async function handler(ctx) { description: utils.renderOGVDescription(embed, item.cover, item.long_title, seasonId, String(item.id)), link: item.share_url, image: item.cover.replace('http://', 'https://'), - language: 'zh-cn', + language: 'zh-CN', }) as DataItem; for (const item of seasonData.main_section.episodes) { @@ -65,6 +65,6 @@ async function handler(ctx) { link: mediaData.share_url, item: episodes, image: mediaData.cover.replace('http://', 'https://'), - language: 'zh-cn', + language: 'zh-CN', } as Data; } diff --git a/lib/routes/bilibili/cache.ts b/lib/routes/bilibili/cache.ts index 0aeaa6e92b..e0aaf0cb7c 100644 --- a/lib/routes/bilibili/cache.ts +++ b/lib/routes/bilibili/cache.ts @@ -121,7 +121,7 @@ const getWbiVerifyString = () => { // 62, 11, 36, 20, 34, 44, 52, // ]; const array = JSON.parse(jsResponse.match(/\[(?:\d+,){63}\d+\]/)); - const o = []; + const o: any[] = []; for (const t of array) { if (r.charAt(t)) { o.push(r.charAt(t)); @@ -328,7 +328,7 @@ const getAidFromBvid = async (bvid) => { if (response.data && response.data.data && response.data.data.aid) { aid = response.data.data.aid; } - cache.set(key, aid); + cache.set(key, aid ?? ''); } return aid; }; @@ -355,7 +355,7 @@ const getArticleDataFromCvid = async (cvid, uid) => { const newFormatData = JSON.parse( $('script:contains("window.__INITIAL_STATE__")') .text() - .match(/window\.__INITIAL_STATE__\s*=\s*(\S.*?)?;\(/)[1] + .match(/window\.__INITIAL_STATE__\s*=\s*(\S.*?)?;\(/)![1] ); if (newFormatData?.readInfo?.opus?.content?.paragraphs) { diff --git a/lib/routes/bilibili/danmaku.ts b/lib/routes/bilibili/danmaku.ts index 0f429e6177..8618cb452b 100644 --- a/lib/routes/bilibili/danmaku.ts +++ b/lib/routes/bilibili/danmaku.ts @@ -59,7 +59,7 @@ async function handler(ctx) { danmakuText = await ((danmakuText[0] & 0x0f) === 0x08 ? zlib.inflateSync(danmakuText) : zlib.inflateRawSync(danmakuText)); - let danmakuList = []; + let danmakuList: any[] = []; const $ = load(danmakuText, { xmlMode: true }); $('d').each((index, item) => { danmakuList.push({ p: $(item).attr('p'), text: $(item).text() }); diff --git a/lib/routes/bilibili/mall-new.ts b/lib/routes/bilibili/mall-new.ts index 212da7d91f..488d20cfff 100644 --- a/lib/routes/bilibili/mall-new.ts +++ b/lib/routes/bilibili/mall-new.ts @@ -36,7 +36,7 @@ async function handler(ctx) { }); const days = response.data.data.vo.days; - const items = []; + const items: any[] = []; for (const day of days) { items.push(...day.presaleItems); } diff --git a/lib/routes/bilibili/user-channel.ts b/lib/routes/bilibili/user-channel.ts index b4e17b8b0e..e1b998c3f8 100644 --- a/lib/routes/bilibili/user-channel.ts +++ b/lib/routes/bilibili/user-channel.ts @@ -69,9 +69,9 @@ async function handler(ctx) { title: `${username} 的 bilibili 频道 ${channelInfo.meta.name}`, link, description: `${username} 的 bilibili 频道`, - image: face, - logo: face, - icon: face, + image: face ?? undefined, + logo: face ?? undefined, + icon: face ?? undefined, item: data.archives.map((item) => ({ title: item.title, description: utils.renderUGCDescription(embed, item.pic, '', item.aid, undefined, item.bvid), diff --git a/lib/routes/bilibili/user-collection.ts b/lib/routes/bilibili/user-collection.ts index 29b3110189..f8916923dd 100644 --- a/lib/routes/bilibili/user-collection.ts +++ b/lib/routes/bilibili/user-collection.ts @@ -61,9 +61,9 @@ async function handler(ctx) { title: `${username} 的 bilibili 合集 ${data.meta.name}`, link, description: `${username} 的 bilibili 合集`, - image: face, - logo: face, - icon: face, + image: face ?? undefined, + logo: face ?? undefined, + icon: face ?? undefined, item: data.archives.map((item) => ({ title: item.title, description: utils.renderUGCDescription(embed, item.pic, '', item.aid, undefined, item.bvid), diff --git a/lib/routes/bilibili/video-all.ts b/lib/routes/bilibili/video-all.ts index 574b17e1fa..3114f721ce 100644 --- a/lib/routes/bilibili/video-all.ts +++ b/lib/routes/bilibili/video-all.ts @@ -24,7 +24,7 @@ async function handler(ctx) { const cookie = await cache.getCookie(); const wbiVerifyString = await cache.getWbiVerifyString(); const dmImgList = utils.getDmImgList(); - const [name, face] = await cache.getUsernameAndFaceFromUID(uid); + const [name, face] = (await cache.getUsernameAndFaceFromUID(uid)) as [string, string]; await got(`https://space.bilibili.com/${uid}/video?tid=0&page=1&keyword=&order=pubdate`, { headers: { @@ -60,7 +60,7 @@ async function handler(ctx) { }); }; - const promises = []; + const promises: Array> = []; if (pageTotal > 1) { for (let i = 2; i <= pageTotal; i++) { diff --git a/lib/routes/bilibili/video.ts b/lib/routes/bilibili/video.ts index c34a821c3b..552711bb8e 100644 --- a/lib/routes/bilibili/video.ts +++ b/lib/routes/bilibili/video.ts @@ -224,7 +224,7 @@ async function handler(ctx: Context) { const uid = ctx.req.param('uid'); const embed = !ctx.req.param('embed'); - const data = await getVideoList(uid); + const data = await getVideoList(uid!); const videos = data.list?.vlist ?? []; let name = videos[0]?.author || uid; @@ -233,7 +233,7 @@ async function handler(ctx: Context) { try { const usernameAndFace = await cache.getUsernameAndFaceFromUID(uid); name = usernameAndFace[0] || name; - face = usernameAndFace[1]; + face = usernameAndFace[1] ?? undefined; } catch (error) { logger.warn(`[bilibili/video] failed to fetch user profile: ${error}`); } @@ -250,7 +250,7 @@ async function handler(ctx: Context) { const subtitles = isJsonFeed && !config.bilibili.excludeSubtitles && item.bvid ? await cache.getVideoSubtitleAttachment(item.bvid) : []; return { title: item.title, - description: utils.renderUGCDescription(embed, item.pic, item.description, item.aid, undefined, item.bvid), + description: utils.renderUGCDescription(embed, item.pic, item.description, String(item.aid), undefined, item.bvid), pubDate: new Date(item.created * 1000).toUTCString(), link: item.created > utils.bvidTime && item.bvid ? `https://www.bilibili.com/video/${item.bvid}` : `https://www.bilibili.com/video/av${item.aid}`, author: name, diff --git a/lib/routes/bilibili/wasm-exec.ts b/lib/routes/bilibili/wasm-exec.ts index 6159de0ac5..9a142d8cfb 100644 --- a/lib/routes/bilibili/wasm-exec.ts +++ b/lib/routes/bilibili/wasm-exec.ts @@ -1,3 +1,4 @@ +// @ts-nocheck https://github.com/golang/go/blob/master/lib/wasm/wasm_exec.js // oxlint-disable unicorn/prefer-math-trunc // oxlint-disable unicorn-js/no-this-outside-of-class // oxlint-disable unicorn-js/no-array-from-fill @@ -598,7 +599,7 @@ const argc = this.argv.length; - const argvPtrs = []; + const argvPtrs: number[] = []; for (const arg of this.argv) { argvPtrs.push(strPtr(arg)); } diff --git a/lib/routes/bing/search.ts b/lib/routes/bing/search.ts index 5faef975aa..4fc24ff233 100644 --- a/lib/routes/bing/search.ts +++ b/lib/routes/bing/search.ts @@ -3,7 +3,7 @@ import 'dayjs/locale/zh-cn.js'; import dayjs from 'dayjs'; import localizedFormat from 'dayjs/plugin/localizedFormat.js'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import { parseDate } from '@/utils/parse-date'; import parser from '@/utils/rss-parser'; @@ -44,14 +44,14 @@ async function handler(ctx) { url.search = searchParams.toString(); const data = await parser.parseURL(url.href); return { - title: data.title, + title: data.title!, link: data.link, description: data.description + ' - ' + data.copyright, - image: data.image.url, + image: data.image!.url, item: data.items.map((e) => ({ ...e, description: e.content, - pubDate: parseDate(e.pubDate, 'dddd, DD MMM YYYY HH:mm:ss [GMT]', 'zh-cn'), - })), + pubDate: parseDate(e.pubDate!, 'dddd, DD MMM YYYY HH:mm:ss [GMT]', 'zh-cn'), + })) as DataItem[], }; } diff --git a/lib/routes/bioone/featured.ts b/lib/routes/bioone/featured.ts index 8afafa0b09..81acced41f 100644 --- a/lib/routes/bioone/featured.ts +++ b/lib/routes/bioone/featured.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -38,25 +38,25 @@ async function handler(ctx) { let items = $('.items h4 a') .slice(0, ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit')) : 10) .toArray() - .map((item) => { - item = $(item); - const link = item.attr('href').split('?', 1)[0]; + .map((item): DataItem => { + const $item = $(item); + const link = $item.attr('href')!.split('?', 1)[0]; return { - title: item.text(), + title: $item.text(), link: link.includes('http') ? link : `${rootUrl}${link}`, }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const detailResponse = await got(item.link); const content = load(detailResponse.data); item.description = content('#divARTICLECONTENTTop').html(); item.doi = content('meta[name="dc.Identifier"]').attr('content'); - item.pubDate = parseDate(content('meta[name="dc.Date"]').attr('content')); + item.pubDate = parseDate(content('meta[name="dc.Date"]').attr('content')!); return item; }) diff --git a/lib/routes/bioone/journal.ts b/lib/routes/bioone/journal.ts index 87ab9f11e0..569b4943f9 100644 --- a/lib/routes/bioone/journal.ts +++ b/lib/routes/bioone/journal.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -41,17 +41,18 @@ async function handler(ctx) { let items = $('.TOCLineItemBoldText') .slice(0, ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit')) : 20) .toArray() - .map((item) => { - item = $(item).parent(); + .map((item): DataItem => { + const $item = $(item).parent(); return { - link: `${rootUrl}${item.attr('href')}`, + title: '', + link: `${rootUrl}${$item.attr('href')}`, }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const detailResponse = await got(item.link); const content = load(detailResponse.data); @@ -60,10 +61,10 @@ async function handler(ctx) { content('#divNotSignedSection, #rightRail').remove(); item.description = content('.panel-body').html(); - item.title = content('meta[name="dc.Title"]').attr('content'); + item.title = content('meta[name="dc.Title"]').attr('content')!; item.author = content('meta[name="dc.Creator"]').attr('content'); item.doi = content('meta[name="dc.Identifier"]').attr('content'); - item.pubDate = parseDate(content('meta[name="dc.Date"]').attr('content')); + item.pubDate = parseDate(content('meta[name="dc.Date"]').attr('content')!); return item; }) diff --git a/lib/routes/biquge/index.ts b/lib/routes/biquge/index.ts index 29286c71c6..a283d9e98c 100644 --- a/lib/routes/biquge/index.ts +++ b/lib/routes/biquge/index.ts @@ -3,7 +3,7 @@ import iconv from 'iconv-lite'; import { config } from '@/config'; import ConfigNotFoundError from '@/errors/types/config-not-found'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -76,27 +76,27 @@ async function handler(ctx) { const $ = load(iconv.decode(response.data, encoding)); const author = $('meta[property="og:novel:author"]').attr('content'); - const pubDate = timezone(parseDate($('meta[property="og:novel:update_time"]').attr('content')), 8); + const pubDate = timezone(parseDate($('meta[property="og:novel:update_time"]').attr('content')!), 8); let items = $('dl dd a') .toArray() .toReversed() .slice(0, ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit')) : 1) - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); let link: string; - const url = item.attr('href'); - if (url.startsWith('http')) { - link = url; - } else if (url.startsWith('/')) { + const url = $item.attr('href'); + if (url!.startsWith('http')) { + link = url!; + } else if (url!.startsWith('/')) { link = `${rootUrl}${url}`; } else { link = `${currentUrl}/${url}`; } return { - title: item.text(), + title: $item.text(), link, author, pubDate, @@ -105,7 +105,7 @@ async function handler(ctx) { items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const detailResponse = await got(item.link, { responseType: 'buffer', }); diff --git a/lib/routes/bit/cs/utils.ts b/lib/routes/bit/cs/utils.ts index ad67790a43..468bb7daa3 100644 --- a/lib/routes/bit/cs/utils.ts +++ b/lib/routes/bit/cs/utils.ts @@ -32,7 +32,7 @@ const ProcessFeed = (list, caches) => { const $title = $('a'); // 还原相对链接为绝对链接 - const itemUrl = new URL($title.attr('href'), host).href; + const itemUrl = new URL($title.attr('href')!, host).href; // 列表上提取到的信息 const single = { diff --git a/lib/routes/bit/jwc/utils.ts b/lib/routes/bit/jwc/utils.ts index 1bcc9b522b..f4cf2c0bb2 100644 --- a/lib/routes/bit/jwc/utils.ts +++ b/lib/routes/bit/jwc/utils.ts @@ -28,7 +28,7 @@ const ProcessFeed = (list, caches) => { const $title = $('a'); // 还原相对链接为绝对链接 - const itemUrl = new URL($title.attr('href'), host).href; + const itemUrl = new URL($title.attr('href')!, host).href; // 列表上提取到的信息 const single = { diff --git a/lib/routes/bit/yjs.ts b/lib/routes/bit/yjs.ts index c20f2aa017..8c71e63df0 100644 --- a/lib/routes/bit/yjs.ts +++ b/lib/routes/bit/yjs.ts @@ -41,12 +41,12 @@ async function handler() { item: list && list.toArray().map((item) => { - item = $(item); - const a = item.find('a'); + const $item = $(item); + const a = $item.find('a'); return { title: a.text(), - link: new URL(a.attr('href'), link).href, - pubDate: parseDate(item.find('span').text(), 'YYYY-MM-DD'), + link: new URL(a.attr('href')!, link).href, + pubDate: parseDate($item.find('span').text(), 'YYYY-MM-DD'), }; }), }; diff --git a/lib/routes/bjfu/grs.ts b/lib/routes/bjfu/grs.ts index 17cb96940f..7d1a8dbcc1 100644 --- a/lib/routes/bjfu/grs.ts +++ b/lib/routes/bjfu/grs.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -38,7 +38,7 @@ async function handler() { const list = $('.itemList li') .slice(0, 11) .toArray() - .map((e) => { + .map((e): DataItem => { const element = $(e); const title = element.find('li a').attr('title'); const link = element.find('li a').attr('href'); @@ -46,10 +46,10 @@ async function handler() { .find('li a') .text() .match(/\d{4}-\d{2}-\d{2}/); - const pubDate = timezone(parseDate(date), 8); + const pubDate = timezone(parseDate(date?.[0] ?? ''), 8); return { - title, + title: title!, link: 'http://graduate.bjfu.edu.cn/pygl/pydt/' + link, author: '北京林业大学研究生院培养动态', pubDate, @@ -58,7 +58,7 @@ async function handler() { const result = await Promise.all( list.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const itemReponse = await got.get(item.link); const data = itemReponse.data; const itemElement = load(data); diff --git a/lib/routes/bjfu/it/utils.ts b/lib/routes/bjfu/it/utils.ts index 2998f726e3..d390d8dc67 100644 --- a/lib/routes/bjfu/it/utils.ts +++ b/lib/routes/bjfu/it/utils.ts @@ -26,7 +26,7 @@ async function loadContent(link) { } // 提取内容 - const description = ($('.template-body').length ? $('.template-body').html() : '') + ($('.template-tail').length ? $('.template-tail').html() : ''); + const description = ($('.template-body').length ? $('.template-body').html() : '')! + ($('.template-tail').length ? $('.template-tail').html() : '')!; // 返回解析的结果 return { description }; @@ -41,14 +41,14 @@ const ProcessFeed = (base, list, caches) => const $title = $('a'); // 还原相对链接为绝对链接 - const itemUrl = new URL($title.attr('href'), base).href; // 感谢@hoilc指导 + const itemUrl = new URL($title.attr('href')!, base).href; // 感谢@hoilc指导 // 解析日期 const pubDate = timezone( parseDate( $('span') .text() - .match(/\d{4}-\d{2}-\d{2}/) + .match(/\d{4}-\d{2}-\d{2}/)?.[0] ?? '' ), 8 ); diff --git a/lib/routes/bjfu/jwc/utils.ts b/lib/routes/bjfu/jwc/utils.ts index 526bbda34d..2f4177b345 100644 --- a/lib/routes/bjfu/jwc/utils.ts +++ b/lib/routes/bjfu/jwc/utils.ts @@ -14,7 +14,7 @@ async function loadContent(link) { const $ = load(data); // 提取内容 - const description = ($('#con_c').length ? $('#con_c').html() : '') + ($('#con_fujian').length ? $('#con_fujian').html() : ''); + const description = ($('#con_c').length ? $('#con_c').html() : '')! + ($('#con_fujian').length ? $('#con_fujian').html() : '')!; // 返回解析的结果 return { description }; @@ -28,14 +28,14 @@ const ProcessFeed = (base, list, caches) => const $title = $('a'); // 还原相对链接为绝对链接 - const itemUrl = new URL($title.attr('href'), base).href; // 感谢@hoilc指导 + const itemUrl = new URL($title.attr('href')!, base).href; // 感谢@hoilc指导 // 解析日期 const pubDate = timezone( parseDate( $('.datetime') .text() - .match(/\d{4}-\d{2}-\d{2}/) + .match(/\d{4}-\d{2}-\d{2}/)?.[0] ?? '' ), 8 ); diff --git a/lib/routes/bjfu/kjc.ts b/lib/routes/bjfu/kjc.ts index dee0e77ed3..4327203c22 100644 --- a/lib/routes/bjfu/kjc.ts +++ b/lib/routes/bjfu/kjc.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -38,7 +38,7 @@ async function handler() { const list = $('.ll_con_r_b li') .slice(0, 15) .toArray() - .map((e) => { + .map((e): DataItem => { const element = $(e); const title = element.find('.ll_con_r_b_title a').text(); const link = element.find('a').attr('href'); @@ -46,7 +46,7 @@ async function handler() { .find('.ll_con_r_b_time') .text() .match(/\d{4}-\d{2}-\d{2}/); - const pubDate = timezone(parseDate(date), 8); + const pubDate = timezone(parseDate(date?.[0] ?? ''), 8); return { title, @@ -58,7 +58,7 @@ async function handler() { const result = await Promise.all( list.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const itemReponse = await got.get(item.link); const data = itemReponse.data; const itemElement = load(data); diff --git a/lib/routes/bjfu/news/index.ts b/lib/routes/bjfu/news/index.ts index 843c7858ec..c218ceed2a 100644 --- a/lib/routes/bjfu/news/index.ts +++ b/lib/routes/bjfu/news/index.ts @@ -69,7 +69,7 @@ async function handler(ctx) { const data = response.data; let $ = load(iconv.decode(data, 'utf-8')); const charset = $('meta[http-equiv="Content-Type"]') - .attr('content') + .attr('content')! .match(/charset=(.*)/)?.[1]; if (charset?.toLowerCase() !== 'utf-8') { $ = load(iconv.decode(data, charset ?? 'utf-8')); diff --git a/lib/routes/bjfu/news/utils.ts b/lib/routes/bjfu/news/utils.ts index b13dcc30b3..8bb8563026 100644 --- a/lib/routes/bjfu/news/utils.ts +++ b/lib/routes/bjfu/news/utils.ts @@ -18,7 +18,7 @@ async function loadContent(link) { parseDate( $('.article') .text() - .match(/\d{4}(?:\/\d{2}){2}/) + .match(/\d{4}(?:\/\d{2}){2}/)?.[0] ?? '' ), 8 ); @@ -39,7 +39,7 @@ const ProcessFeed = (base, list, caches) => const $title = $('a'); // 还原相对链接为绝对链接 - const itemUrl = new URL($title.attr('href'), base).href; // 感谢@hoilc指导 + const itemUrl = new URL($title.attr('href')!, base).href; // 感谢@hoilc指导 // 使用tryGet方法从缓存获取内容。 // 当缓存中无法获取到链接内容的时候,则使用load方法加载文章内容。 diff --git a/lib/routes/bjp/apod.ts b/lib/routes/bjp/apod.ts index 8fcc8bed6f..084585920e 100644 --- a/lib/routes/bjp/apod.ts +++ b/lib/routes/bjp/apod.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import { ViewType } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; @@ -42,20 +42,20 @@ async function handler(ctx) { const list = $('td[align=left] b') .toArray() - .map((e) => { - e = $(e); + .map((e): DataItem => { + const $e = $(e); return { - title: e.find('a').attr('title'), - link: `${baseUrl}${e.find('a').attr('href')}`, - pubDate: timezone(parseDate(e.find('span').text().replace(':', ''), 'YYYY-MM-DD'), 8), + title: $e.find('a').attr('title')!, + link: `${baseUrl}${$e.find('a').attr('href')}`, + pubDate: timezone(parseDate($e.find('span').text().replace(':', ''), 'YYYY-MM-DD'), 8), }; }) - .toSorted((a, b) => b.pubDate - a.pubDate) + .toSorted((a, b) => Number(b.pubDate) - Number(a.pubDate)) .slice(0, ctx.req.query('limit') ? Number(ctx.req.query('limit')) : 10); const items = await Promise.all( list.map((e) => - cache.tryGet(e.link, async () => { + cache.tryGet(e.link!, async () => { const { data } = await got.get(e.link); const $ = load(data); diff --git a/lib/routes/bjsk/index.ts b/lib/routes/bjsk/index.ts index e5deceeea0..4ae39a1793 100644 --- a/lib/routes/bjsk/index.ts +++ b/lib/routes/bjsk/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -38,24 +38,24 @@ async function handler(ctx) { const list = $('.article-list a') .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); return { - title: item.attr('title'), - link: `${baseUrl}${item.attr('href')}`, - pubDate: parseDate(item.find('.time').text(), 'YYYY.MM.DD'), + title: $item.attr('title')!, + link: `${baseUrl}${$item.attr('href')}`, + pubDate: parseDate($item.find('.time').text(), 'YYYY.MM.DD'), }; }); const items = await Promise.all( list.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const { data: response } = await got(item.link); const $ = load(response); item.description = $('.article-main').html(); item.author = $('.info') .text() - .match(/作者:(.*?)来源/)[1] + .match(/作者:(.*?)来源/)![1] .trim(); return item; }) diff --git a/lib/routes/bjsk/keti.ts b/lib/routes/bjsk/keti.ts index ea706b6f66..f11a475a0e 100644 --- a/lib/routes/bjsk/keti.ts +++ b/lib/routes/bjsk/keti.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -49,19 +49,19 @@ async function handler(ctx) { let items = $('a.news') .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); return { - title: item.find('.zizizi').text(), - link: `${rootUrl}${item.attr('href')}`, - pubDate: parseDate(item.find('.date').text()), + title: $item.find('.zizizi').text(), + link: `${rootUrl}${$item.attr('href')}`, + pubDate: parseDate($item.find('.date').text()), }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const detailResponse = await got({ method: 'get', url: item.link, diff --git a/lib/routes/bjwxdxh/index.ts b/lib/routes/bjwxdxh/index.ts index 5b7a58cfe1..eafa3f7ffa 100644 --- a/lib/routes/bjwxdxh/index.ts +++ b/lib/routes/bjwxdxh/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -40,18 +40,18 @@ async function handler(ctx) { const $ = load(response.data); const list = $('div#newsquery > ul > li') .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); return { - title: item.find('div.title > a').text(), - link: new URL(item.find('div.title > a').attr('href'), baseUrl).href, + title: $item.find('div.title > a').text(), + link: new URL($item.find('div.title > a').attr('href')!, baseUrl).href, // pubDate: parseDate(item.find('div.time').text(), 'YYYY-MM-DD'), }; }); await Promise.all( list.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const response = await got({ method: 'get', url: item.link, @@ -60,9 +60,9 @@ async function handler(ctx) { const info = content('div.info') .text() .match(/作者:(\S*)\s+发布于:(\S*\s+.*?)\s/); - item.author = info[1]; - item.pubDate = timezone(parseDate(info[2], 'YYYY-MM-DD HH:mm:ss'), 8); - item.description = content('div#con').html().replaceAll('\n', ''); + item.author = info![1]; + item.pubDate = timezone(parseDate(info![2], 'YYYY-MM-DD HH:mm:ss'), 8); + item.description = content('div#con').html()!.replaceAll('\n', ''); return item; }) ) diff --git a/lib/routes/bjx/huanbao.ts b/lib/routes/bjx/huanbao.ts index 33ff748fcf..eaf3f6b82c 100644 --- a/lib/routes/bjx/huanbao.ts +++ b/lib/routes/bjx/huanbao.ts @@ -1,3 +1,4 @@ +import type { CheerioAPI } from 'cheerio'; import { load } from 'cheerio'; import pMap from 'p-map'; @@ -39,11 +40,11 @@ async function handler() { let items = $('.cc-layout-3 .cc-list-content li') .toArray() .map((e) => { - e = $(e); + const $e = $(e); return { - title: e.find('a').attr('title'), - link: e.find('a').attr('href'), - pubDate: parseDate(e.find('span').text()), + title: $e.find('a').attr('title')!, + link: $e.find('a').attr('href'), + pubDate: parseDate($e.find('span').text()), }; }); @@ -64,7 +65,7 @@ async function handler() { const fetchPage = (link) => cache.tryGet(link, async () => { // 可能一篇文章过长会分成多页 - const pages = []; + const pages: CheerioAPI[] = []; const result = await got(link); const $page = load(result.data); @@ -79,7 +80,7 @@ const fetchPage = (link) => if (!/^\d+$/.test($a.text().trim())) { continue; } - const sublink = new URL($a.attr('href'), link).href; + const sublink = new URL($a.attr('href')!, link).href; /* eslint-disable no-await-in-loop */ const result = await got(sublink); pages.push(load(result.data)); diff --git a/lib/routes/bjx/types.ts b/lib/routes/bjx/types.ts index 3dd8f58c99..597bfcfedc 100644 --- a/lib/routes/bjx/types.ts +++ b/lib/routes/bjx/types.ts @@ -42,12 +42,12 @@ async function handler(ctx) { description: $('meta[name="Description"]').attr('content'), link: `https://guangfu.bjx.com.cn/${type}/`, item: list.toArray().map((item) => { - item = $(item); + const $item = $(item); return { - title: item.find('a').attr('title'), - description: item.html(), - link: item.find('a').attr('href'), - pubDate: parseDate(item.find('span').text()), + title: $item.find('a').attr('title')!, + description: $item.html(), + link: $item.find('a').attr('href'), + pubDate: parseDate($item.find('span').text()), }; }), }; diff --git a/lib/routes/blizzard/news-cn.ts b/lib/routes/blizzard/news-cn.ts index e0d38c71c3..bb2e468467 100644 --- a/lib/routes/blizzard/news-cn.ts +++ b/lib/routes/blizzard/news-cn.ts @@ -52,39 +52,39 @@ const parsers = { $('.list-data-container .list-item-container') .toArray() .map((item) => { - item = $(item); + const $item = $(item); return { - title: item.find('.content-title').text(), - link: item.find('.fill-link').attr('href'), - description: item.find('.content-intro').text(), - pubDate: parseDate(item.find('.content-date').text()), - image: item.find('.item-pic').attr('src'), + title: $item.find('.content-title').text(), + link: $item.find('.fill-link').attr('href'), + description: $item.find('.content-intro').text(), + pubDate: parseDate($item.find('.content-date').text()), + image: $item.find('.item-pic').attr('src'), }; }), hs: ($) => $('.article-container>a') .toArray() .map((item) => { - item = $(item); + const $item = $(item); return { - title: item.find('.title').text(), - link: item.attr('href'), - description: item.find('.desc').text(), - pubDate: parseDate(item.find('.date').attr('data-time')), - image: item.find('.article-img img').attr('src'), + title: $item.find('.title').text(), + link: $item.attr('href'), + description: $item.find('.desc').text(), + pubDate: parseDate($item.find('.date').attr('data-time')), + image: $item.find('.article-img img').attr('src'), }; }), wow: ($) => $('.Pane-list>a') .toArray() .map((item) => { - item = $(item); + const $item = $(item); return { - title: item.find('.list-title').text(), - link: item.attr('href'), - description: item.find('.list-desc').text(), - pubDate: parseDate(item.find('.list-time').attr('data-time')), - image: item.find('.img-box img').attr('src'), + title: $item.find('.list-title').text(), + link: $item.attr('href'), + description: $item.find('.list-desc').text(), + pubDate: parseDate($item.find('.list-time').attr('data-time')), + image: $item.find('.img-box img').attr('src'), }; }), }; diff --git a/lib/routes/blockworks/index.ts b/lib/routes/blockworks/index.ts index e09cac3115..341fa59166 100644 --- a/lib/routes/blockworks/index.ts +++ b/lib/routes/blockworks/index.ts @@ -44,10 +44,7 @@ async function handler(ctx): Promise { const items = await Promise.all( limitedItems - .map((item) => ({ - ...item, - link: item.link?.split('?', 1)[0], - })) + .map((item) => ({ ...item, link: item.link?.split('?', 1)[0] }) as typeof item & { author?: DataItem['author'] }) .map((item) => cache.tryGet(item.link!, async () => { // Get cached content or fetch new content diff --git a/lib/routes/blogread/index.ts b/lib/routes/blogread/index.ts index 8ccfff9c0a..c6bd77640d 100644 --- a/lib/routes/blogread/index.ts +++ b/lib/routes/blogread/index.ts @@ -27,14 +27,14 @@ async function handler() { const resultItem = $('.media') .toArray() .map((elem) => { - elem = $(elem); - const $link = elem.find('dt a'); + const $elem = $(elem); + const $link = $elem.find('dt a'); return { title: $link.text(), - description: elem.find('dd').eq(0).text(), + description: $elem.find('dd').eq(0).text(), link: $link.attr('href'), - author: elem.find('.small a').eq(0).text(), - pubDate: elem.find('dd').eq(1).text().split('\n', 3)[2], + author: $elem.find('.small a').eq(0).text(), + pubDate: $elem.find('dd').eq(1).text().split('\n', 3)[2], }; }); return { diff --git a/lib/routes/bloomberg/authors.ts b/lib/routes/bloomberg/authors.ts index bcee63b7f8..a3ae76bcc8 100644 --- a/lib/routes/bloomberg/authors.ts +++ b/lib/routes/bloomberg/authors.ts @@ -1,7 +1,7 @@ import { load } from 'cheerio'; import pMap from 'p-map'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import { ViewType } from '@/types'; import ofetch from '@/utils/ofetch'; import rssParser from '@/utils/rss-parser'; @@ -19,13 +19,13 @@ const parseAuthorNewsList = async (slug) => { const $ = load(resp.html); const articles = $('article.story-list-story'); return articles.toArray().map((item) => { - item = $(item); - const headline = item.find('a.story-list-story__info__headline-link'); + const $item = $(item); + const headline = $item.find('a.story-list-story__info__headline-link'); return { title: headline.text(), - pubDate: item.attr('data-updated-at'), - guid: `bloomberg:${item.attr('data-id')}`, - link: new URL(headline.attr('href'), baseURL).href, + pubDate: $item.attr('data-updated-at'), + guid: `bloomberg:${$item.attr('data-id')}`, + link: new URL(headline.attr('href')!, baseURL).href, }; }); }; @@ -59,7 +59,7 @@ async function handler(ctx) { const { id, slug, source } = ctx.req.param(); const link = `https://www.bloomberg.com/authors/${id}/${slug}`; - let list = []; + let list: any[] = []; if (!source || source === 'api') { list = await parseAuthorNewsList(`${id}/${slug}`); } @@ -74,7 +74,7 @@ async function handler(ctx) { return { title: `Bloomberg - ${authorName}`, link, - language: 'en-us', + language: 'en-us' as Language, item, }; } diff --git a/lib/routes/bloomberg/templates/lede-media.tsx b/lib/routes/bloomberg/templates/lede-media.tsx index fe8238bc24..296a938aa9 100644 --- a/lib/routes/bloomberg/templates/lede-media.tsx +++ b/lib/routes/bloomberg/templates/lede-media.tsx @@ -3,7 +3,7 @@ import { renderToString } from 'hono/jsx/dom/server'; import { renderVideoMedia } from './video-media'; -type LedeMedia = { +export type LedeMedia = { kind?: string; src?: string; description?: string; diff --git a/lib/routes/bloomberg/templates/video-media.tsx b/lib/routes/bloomberg/templates/video-media.tsx index 8b8b7a1471..8475b4f199 100644 --- a/lib/routes/bloomberg/templates/video-media.tsx +++ b/lib/routes/bloomberg/templates/video-media.tsx @@ -13,7 +13,7 @@ export const renderVideoMedia = ({ stream, mp4, coverUrl, caption }: VideoMediaD