diff --git a/docs/en/parameter.md b/docs/en/parameter.md index c05e1cf837..c8f49c6f54 100644 --- a/docs/en/parameter.md +++ b/docs/en/parameter.md @@ -36,6 +36,12 @@ Set `filterout` to exclude unwanted content. For example: [https://rsshub.app/dribbble/popular?filterout=Blue|Yellow|Black](https://rsshub.app/dribbble/popular?filterout=Blue|Yellow|Black) +Set `filter_case_sensitive` to determine whether the filtering keywords should be case sensitive. The parameter would apply to both `filter` and `filterout`. + +Default: `true` + +Example: [https://rsshub.app/dribbble/popular?filter=BluE|yeLLow|BlaCK&filter_case_sensitive=false](https://rsshub.app/dribbble/popular?filter=BluE|yeLLow|BlaCK&filter_case_sensitive=false) + ### Limit Entries Set `limit` to limit the number of articles in the feed. diff --git a/docs/parameter.md b/docs/parameter.md index a0c6fda29d..fea10e941b 100644 --- a/docs/parameter.md +++ b/docs/parameter.md @@ -37,6 +37,12 @@ filterout 去掉不要的内容 举例: +filter_case_sensitive 过滤是否区分大小写,filter 和 filterout 同时适用 + +默认为 true,区分大小写 + +举例 1: + ## 条数限制 可以使用 limit 参数限制最大条数, 主要用于排行榜类 RSS diff --git a/lib/middleware/parameter.js b/lib/middleware/parameter.js index 843ace5861..3e3779fb6c 100644 --- a/lib/middleware/parameter.js +++ b/lib/middleware/parameter.js @@ -121,6 +121,15 @@ module.exports = async (ctx, next) => { } // filter + const makeRegex = (string) => { + // default: case_senstivie = true + if (ctx.query.filter_case_sensitive === 'false') { + return new RegExp(string, 'i'); + } else { + return new RegExp(string); + } + }; + if (ctx.query.filter || ctx.query.filter_title || ctx.query.filter_description || ctx.query.filter_author) { if (ctx.query.filter) { ctx.query.filter_title = ctx.query.filter; @@ -131,9 +140,9 @@ module.exports = async (ctx, next) => { const description = item.description || title; const author = item.author || ''; let isFilter = true; - ctx.query.filter_title && (isFilter = isFilter && !title.match(ctx.query.filter_title)); - ctx.query.filter_description && (isFilter = isFilter && !description.match(ctx.query.filter_description)); - ctx.query.filter_author && (isFilter = isFilter && !author.match(ctx.query.filter_author)); + ctx.query.filter_title && (isFilter = isFilter && !title.match(makeRegex(ctx.query.filter_title))); + ctx.query.filter_description && (isFilter = isFilter && !description.match(makeRegex(ctx.query.filter_description))); + ctx.query.filter_author && (isFilter = isFilter && !author.match(makeRegex(ctx.query.filter_author))); return !isFilter; }); } @@ -148,9 +157,9 @@ module.exports = async (ctx, next) => { const description = item.description || title; const author = item.author || ''; let isFilter = true; - ctx.query.filterout_title && (isFilter = isFilter && !title.match(ctx.query.filterout_title)); - ctx.query.filterout_description && (isFilter = isFilter && !description.match(ctx.query.filterout_description)); - ctx.query.filterout_author && (isFilter = isFilter && !author.match(ctx.query.filterout_author)); + ctx.query.filterout_title && (isFilter = isFilter && !title.match(makeRegex(ctx.query.filterout_title))); + ctx.query.filterout_description && (isFilter = isFilter && !description.match(makeRegex(ctx.query.filterout_description))); + ctx.query.filterout_author && (isFilter = isFilter && !author.match(makeRegex(ctx.query.filterout_author))); return isFilter; }); } diff --git a/test/middleware/parameter.js b/test/middleware/parameter.js index 3a6f113c55..c16afe963d 100644 --- a/test/middleware/parameter.js +++ b/test/middleware/parameter.js @@ -19,6 +19,20 @@ describe('filter', () => { expect(parsed.items[1].title).toBe('Title5'); }); + it(`filter filter_case_sensitive default`, async () => { + const response = await request.get('/test/1?filter=description4|title5'); + const parsed = await parser.parseString(response.text); + expect(parsed.items.length).toBe(0); + }); + + it(`filter filter_case_sensitive=false`, async () => { + const response = await request.get('/test/1?filter=description4|title5&filter_case_sensitive=false'); + const parsed = await parser.parseString(response.text); + expect(parsed.items.length).toBe(2); + expect(parsed.items[0].title).toBe('Title4'); + expect(parsed.items[1].title).toBe('Title5'); + }); + it(`filter_title`, async () => { const response = await request.get('/test/1?filter_title=Description4|Title5'); const parsed = await parser.parseString(response.text); @@ -26,6 +40,13 @@ describe('filter', () => { expect(parsed.items[0].title).toBe('Title5'); }); + it(`filter_title filter_case_sensitive=false`, async () => { + const response = await request.get('/test/1?filter_title=description4|title5&filter_case_sensitive=false'); + const parsed = await parser.parseString(response.text); + expect(parsed.items.length).toBe(1); + expect(parsed.items[0].title).toBe('Title5'); + }); + it(`filter_description`, async () => { const response = await request.get('/test/1?filter_description=Description4|Title5'); const parsed = await parser.parseString(response.text); @@ -33,6 +54,13 @@ describe('filter', () => { expect(parsed.items[0].title).toBe('Title4'); }); + it(`filter_description filter_case_sensitive=false`, async () => { + const response = await request.get('/test/1?filter_description=description4|title5&filter_case_sensitive=false'); + const parsed = await parser.parseString(response.text); + expect(parsed.items.length).toBe(1); + expect(parsed.items[0].title).toBe('Title4'); + }); + it(`filter_author`, async () => { const response = await request.get('/test/1?filter_author=DIYgod4|DIYgod5'); const parsed = await parser.parseString(response.text); @@ -41,6 +69,20 @@ describe('filter', () => { expect(parsed.items[1].title).toBe('Title5'); }); + it(`filter_author filter_case_sensitive default`, async () => { + const response = await request.get('/test/1?filter_author=diygod4|diygod5'); + const parsed = await parser.parseString(response.text); + expect(parsed.items.length).toBe(0); + }); + + it(`filter_author filter_case_sensitive=false`, async () => { + const response = await request.get('/test/1?filter_author=diygod4|diygod5&filter_case_sensitive=false'); + const parsed = await parser.parseString(response.text); + expect(parsed.items.length).toBe(2); + expect(parsed.items[0].title).toBe('Title4'); + expect(parsed.items[1].title).toBe('Title5'); + }); + it(`filter_time`, async () => { const response = await request.get('/test/current_time?filter_time=25'); const parsed = await parser.parseString(response.text); @@ -58,6 +100,24 @@ describe('filter', () => { expect(parsed.items[2].title).toBe('Title3'); }); + it(`filterout filter_case_sensitive default`, async () => { + const response = await request.get('/test/1?filterout=description4|title5'); + const parsed = await parser.parseString(response.text); + expect(parsed.items.length).toBe(5); + expect(parsed.items[0].title).toBe('Title1'); + expect(parsed.items[1].title).toBe('Title2'); + expect(parsed.items[2].title).toBe('Title3'); + }); + + it(`filterout filter_case_sensitive=false`, async () => { + const response = await request.get('/test/1?filterout=description4|title5&filter_case_sensitive=false'); + const parsed = await parser.parseString(response.text); + expect(parsed.items.length).toBe(3); + expect(parsed.items[0].title).toBe('Title1'); + expect(parsed.items[1].title).toBe('Title2'); + expect(parsed.items[2].title).toBe('Title3'); + }); + it(`filterout_title`, async () => { const response = await request.get('/test/1?filterout_title=Description4|Title5'); const parsed = await parser.parseString(response.text); @@ -68,6 +128,16 @@ describe('filter', () => { expect(parsed.items[3].title).toBe('Title4'); }); + it(`filterout_title filter_case_sensitive=false`, async () => { + const response = await request.get('/test/1?filterout_title=description4|title5&filter_case_sensitive=false'); + const parsed = await parser.parseString(response.text); + expect(parsed.items.length).toBe(4); + expect(parsed.items[0].title).toBe('Title1'); + expect(parsed.items[1].title).toBe('Title2'); + expect(parsed.items[2].title).toBe('Title3'); + expect(parsed.items[3].title).toBe('Title4'); + }); + it(`filterout_description`, async () => { const response = await request.get('/test/1?filterout_description=Description4|Title5'); const parsed = await parser.parseString(response.text); @@ -78,6 +148,16 @@ describe('filter', () => { expect(parsed.items[3].title).toBe('Title5'); }); + it(`filterout_description filter_case_sensitive=false`, async () => { + const response = await request.get('/test/1?filterout_description=description4|title5&filter_case_sensitive=false'); + const parsed = await parser.parseString(response.text); + expect(parsed.items.length).toBe(4); + expect(parsed.items[0].title).toBe('Title1'); + expect(parsed.items[1].title).toBe('Title2'); + expect(parsed.items[2].title).toBe('Title3'); + expect(parsed.items[3].title).toBe('Title5'); + }); + it(`filterout_author`, async () => { const response = await request.get('/test/1?filterout_author=DIYgod4|DIYgod5'); const parsed = await parser.parseString(response.text); @@ -86,6 +166,24 @@ describe('filter', () => { expect(parsed.items[1].title).toBe('Title2'); expect(parsed.items[2].title).toBe('Title3'); }); + + it(`filterout_author filter_case_sensitive default`, async () => { + const response = await request.get('/test/1?filterout_author=diygod4|diygod5'); + const parsed = await parser.parseString(response.text); + expect(parsed.items.length).toBe(5); + expect(parsed.items[0].title).toBe('Title1'); + expect(parsed.items[1].title).toBe('Title2'); + expect(parsed.items[2].title).toBe('Title3'); + }); + + it(`filterout_author filter_case_sensitive=false`, async () => { + const response = await request.get('/test/1?filterout_author=diygod4|diygod5&filter_case_sensitive=false'); + const parsed = await parser.parseString(response.text); + expect(parsed.items.length).toBe(3); + expect(parsed.items[0].title).toBe('Title1'); + expect(parsed.items[1].title).toBe('Title2'); + expect(parsed.items[2].title).toBe('Title3'); + }); }); describe('limit', () => {