From 90eb7bbacf32d56c1f5f8d2951b9aae50ef5659a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=9C=E9=98=91=E5=90=AC=E9=A3=8E?= Date: Mon, 23 Jun 2025 00:42:44 +0800 Subject: [PATCH] feat: support float score threshold for douban (#19425) * support float score threshold for douban * add readable-social tests --- lib/routes/douban/other/list.ts | 6 +-- lib/utils/readable-social.test.ts | 65 +++++++++++++++++++++++++++++++ lib/utils/readable-social.ts | 16 +++++++- 3 files changed, 83 insertions(+), 4 deletions(-) create mode 100644 lib/utils/readable-social.test.ts diff --git a/lib/routes/douban/other/list.ts b/lib/routes/douban/other/list.ts index 3c9ac4df4..47fbc7886 100644 --- a/lib/routes/douban/other/list.ts +++ b/lib/routes/douban/other/list.ts @@ -3,7 +3,7 @@ import { Route } from '@/types'; import got from '@/utils/got'; import path from 'node:path'; import { art } from '@/utils/render'; -import { fallback, queryToInteger } from '@/utils/readable-social'; +import { fallback, queryToInteger, queryToFloat } from '@/utils/readable-social'; export const route: Route = { path: '/list/:type?/:routeParams?', @@ -52,7 +52,7 @@ export const route: Route = { | 额外参数 | 含义 | 接受的值 | 默认值 | | -------- | ---------------------- | -------- | ------ | | playable | 仅看有可播放片源的影片 | 0/1 | 0 | -| score | 筛选评分 | 0-10 | 0 | +| score | 筛选评分 | 0.0-10.0 | 0 | 用例:\`/douban/list/tv_korean/playable=1&score=8\` @@ -67,7 +67,7 @@ async function handler(ctx) { const type = ctx.req.param('type') || 'subject_real_time_hotest'; const routeParams = Object.fromEntries(new URLSearchParams(ctx.req.param('routeParams'))); const playable = fallback(undefined, queryToInteger(routeParams.playable), 0); - const score = fallback(undefined, queryToInteger(routeParams.score), 0); + const score = fallback(undefined, queryToFloat(routeParams.score), 0); let start = 0; const count = 50; let items = []; diff --git a/lib/utils/readable-social.test.ts b/lib/utils/readable-social.test.ts new file mode 100644 index 000000000..142dd7879 --- /dev/null +++ b/lib/utils/readable-social.test.ts @@ -0,0 +1,65 @@ +import { describe, expect, test } from 'vitest'; +import { fallback, queryToBoolean, queryToInteger, queryToFloat } from './readable-social'; + +describe('fallback', () => { + test('应该返回第一个存在的参数', () => { + expect(fallback('primary', 'secondary', 'default')).toBe('primary'); + expect(fallback(undefined, 42, 0)).toBe(42); + expect(fallback(null, '', 'default')).toBe(''); + }); + + test('应该返回默认值', () => { + expect(fallback(undefined, null, 'default')).toBe('default'); + expect(fallback(null, undefined, 3.14)).toBe(3.14); + }); +}); + +describe('queryToBoolean', () => { + test('should handle truthy values', () => { + expect(queryToBoolean('1')).toBe(true); + expect(queryToBoolean('true')).toBe(true); + }); + + test('should handle falsy values', () => { + expect(queryToBoolean('0')).toBe(false); + expect(queryToBoolean('false')).toBe(false); + }); +}); + +describe('queryToInteger', () => { + test('should parse valid integers', () => { + expect(queryToInteger('42')).toBe(42); + expect(queryToInteger('-3')).toBe(-3); + }); + + test('should handle invalid inputs', () => { + expect(queryToInteger(null)).toBeNull(); + expect(queryToInteger('abc')).toBeNaN(); + }); +}); + +describe('queryToFloat', () => { + test('should handle undefined', () => { + expect(queryToFloat(undefined)).toBeUndefined(); + }); + + test('should handle null', () => { + expect(queryToFloat(null)).toBeNull(); + }); + + test('should return undefined for invalid input', () => { + expect(queryToFloat('invalid')).toBeNaN(); + }); + + test('should process array input', () => { + expect(queryToFloat(['3.14'])).toBe(3.14); + }); + + test('should convert numeric string', () => { + expect(queryToFloat('9.8')).toBe(9.8); + }); + + test('should handle edge cases', () => { + expect(queryToFloat('3.1415926')).toBeCloseTo(3.141_592_6); + }); +}); \ No newline at end of file diff --git a/lib/utils/readable-social.ts b/lib/utils/readable-social.ts index 2f63979b8..abed12271 100644 --- a/lib/utils/readable-social.ts +++ b/lib/utils/readable-social.ts @@ -39,4 +39,18 @@ const queryToInteger = (s) => { return Number.parseInt(s); }; -export { fallback, queryToBoolean, queryToInteger }; +const queryToFloat = (s) => { + if (s === undefined || s === null) { + return s; + } + if (Array.isArray(s)) { + if (s.length === 0) { + return; + } + s = s[0]; + } + s = s.toString(); + return Number.parseFloat(s); +}; + +export { fallback, queryToBoolean, queryToInteger, queryToFloat };