mirror of
https://github.com/DIYgod/RSSHub.git
synced 2025-12-08 14:07:54 +08:00
feat(core): filter category (#10212)
This commit is contained in:
@@ -48,6 +48,8 @@ Set `filter` to include the content
|
|||||||
|
|
||||||
- `filter_author`: filter `author` only
|
- `filter_author`: filter `author` only
|
||||||
|
|
||||||
|
- `filter_category`: filter `category` only
|
||||||
|
|
||||||
- `filter_time`: filter `pubDate`, in seconds, return specified time range. Item without `pubDate` will not be filtered.
|
- `filter_time`: filter `pubDate`, in seconds, return specified time range. Item without `pubDate` will not be filtered.
|
||||||
|
|
||||||
E.g. [https://rsshub.app/dribbble/popular?filter=Blue|Yellow|Black](https://rsshub.app/dribbble/popular?filter=Blue|Yellow|Black)
|
E.g. [https://rsshub.app/dribbble/popular?filter=Blue|Yellow|Black](https://rsshub.app/dribbble/popular?filter=Blue|Yellow|Black)
|
||||||
@@ -62,6 +64,8 @@ Set `filterout` to exclude unwanted content.
|
|||||||
|
|
||||||
- `filterout_author`: filter `author` only
|
- `filterout_author`: filter `author` only
|
||||||
|
|
||||||
|
- `filterout_category`: filter `category` only
|
||||||
|
|
||||||
E.g. [https://rsshub.app/dribbble/popular?filterout=Blue|Yellow|Black](https://rsshub.app/dribbble/popular?filterout=Blue|Yellow|Black)
|
E.g. [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`.
|
Set `filter_case_sensitive` to determine whether the filtering keywords should be case sensitive. The parameter would apply to both `filter` and `filterout`.
|
||||||
|
|||||||
@@ -46,6 +46,8 @@ filter 支持正则表达式。由于正则部分特性可被利用于 DoS (ReDO
|
|||||||
|
|
||||||
- `filter_author`: 过滤作者
|
- `filter_author`: 过滤作者
|
||||||
|
|
||||||
|
- `filter_category`: 过滤分类
|
||||||
|
|
||||||
- `filter_time`: 过滤时间,仅支持数字,单位为秒。返回指定时间范围内的内容。如果条目没有输出`pubDate`或者格式不正确将不会被过滤
|
- `filter_time`: 过滤时间,仅支持数字,单位为秒。返回指定时间范围内的内容。如果条目没有输出`pubDate`或者格式不正确将不会被过滤
|
||||||
|
|
||||||
举例 1: `https://rsshub.app/bilibili/fav/2267573/801952073?filter=编曲|摄影`
|
举例 1: `https://rsshub.app/bilibili/fav/2267573/801952073?filter=编曲|摄影`
|
||||||
@@ -61,6 +63,8 @@ filter 支持正则表达式。由于正则部分特性可被利用于 DoS (ReDO
|
|||||||
|
|
||||||
- `filterout_author`: 过滤作者
|
- `filterout_author`: 过滤作者
|
||||||
|
|
||||||
|
- `filterout_category`: 过滤分类
|
||||||
|
|
||||||
举例: `https://rsshub.app/bilibili/fav/2267573/801952073?filterout=编曲|摄影`
|
举例: `https://rsshub.app/bilibili/fav/2267573/801952073?filterout=编曲|摄影`
|
||||||
|
|
||||||
`filter_case_sensitive` 过滤是否区分大小写,`filter` 和 `filterout`同时适用
|
`filter_case_sensitive` 过滤是否区分大小写,`filter` 和 `filterout`同时适用
|
||||||
|
|||||||
@@ -179,26 +179,30 @@ module.exports = async (ctx, next) => {
|
|||||||
const title = item.title || '';
|
const title = item.title || '';
|
||||||
const description = item.description || title;
|
const description = item.description || title;
|
||||||
const author = item.author || '';
|
const author = item.author || '';
|
||||||
const isFilter = title.match(makeRegex(ctx.query.filter)) || description.match(makeRegex(ctx.query.filter)) || author.match(makeRegex(ctx.query.filter));
|
const category = item.category || [];
|
||||||
|
const isFilter =
|
||||||
|
title.match(makeRegex(ctx.query.filter)) || description.match(makeRegex(ctx.query.filter)) || author.match(makeRegex(ctx.query.filter)) || category.some((c) => c.match(makeRegex(ctx.query.filter)));
|
||||||
return isFilter;
|
return isFilter;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 启用filter参数时,无效filter_title/description/author
|
// 启用filter参数时,无效filter_title/description/author/category
|
||||||
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_description || ctx.query.filter_author || ctx.query.filter_category)) {
|
||||||
ctx.state.data.item = ctx.state.data.item.filter((item) => {
|
ctx.state.data.item = ctx.state.data.item.filter((item) => {
|
||||||
const title = item.title || '';
|
const title = item.title || '';
|
||||||
const description = item.description || title;
|
const description = item.description || title;
|
||||||
const author = item.author || '';
|
const author = item.author || '';
|
||||||
|
const category = item.category || [];
|
||||||
let isFilter = true;
|
let isFilter = true;
|
||||||
ctx.query.filter_title && (isFilter = title.match(makeRegex(ctx.query.filter_title)));
|
ctx.query.filter_title && (isFilter = title.match(makeRegex(ctx.query.filter_title)));
|
||||||
ctx.query.filter_description && (isFilter = isFilter && description.match(makeRegex(ctx.query.filter_description)));
|
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)));
|
ctx.query.filter_author && (isFilter = isFilter && author.match(makeRegex(ctx.query.filter_author)));
|
||||||
|
ctx.query.filter_category && (isFilter = isFilter && category.some((c) => c.match(makeRegex(ctx.query.filter_category))));
|
||||||
return isFilter;
|
return isFilter;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx.query.filterout || ctx.query.filterout_title || ctx.query.filterout_description || ctx.query.filterout_author) {
|
if (ctx.query.filterout || ctx.query.filterout_title || ctx.query.filterout_description || ctx.query.filterout_author || ctx.query.filterout_category) {
|
||||||
if (ctx.query.filterout) {
|
if (ctx.query.filterout) {
|
||||||
ctx.query.filterout_title = ctx.query.filterout;
|
ctx.query.filterout_title = ctx.query.filterout;
|
||||||
ctx.query.filterout_description = ctx.query.filterout;
|
ctx.query.filterout_description = ctx.query.filterout;
|
||||||
@@ -207,10 +211,12 @@ module.exports = async (ctx, next) => {
|
|||||||
const title = item.title;
|
const title = item.title;
|
||||||
const description = item.description || title;
|
const description = item.description || title;
|
||||||
const author = item.author || '';
|
const author = item.author || '';
|
||||||
|
const category = item.category || [];
|
||||||
let isFilter = true;
|
let isFilter = true;
|
||||||
ctx.query.filterout_title && (isFilter = !title.match(makeRegex(ctx.query.filterout_title)));
|
ctx.query.filterout_title && (isFilter = !title.match(makeRegex(ctx.query.filterout_title)));
|
||||||
ctx.query.filterout_description && (isFilter = isFilter && !description.match(makeRegex(ctx.query.filterout_description)));
|
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)));
|
ctx.query.filterout_author && (isFilter = isFilter && !author.match(makeRegex(ctx.query.filterout_author)));
|
||||||
|
ctx.query.filterout_category && (isFilter = isFilter && !category.some((c) => c.match(makeRegex(ctx.query.filterout_category))));
|
||||||
return isFilter;
|
return isFilter;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ module.exports = async (ctx) => {
|
|||||||
pubDate: new Date(`2019-3-1`).toUTCString(),
|
pubDate: new Date(`2019-3-1`).toUTCString(),
|
||||||
link: `https://github.com/DIYgod/RSSHub/issues/-1`,
|
link: `https://github.com/DIYgod/RSSHub/issues/-1`,
|
||||||
author: `DIYgod0`,
|
author: `DIYgod0`,
|
||||||
|
category: ['Category0', 'Category1'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Filter Title2',
|
title: 'Filter Title2',
|
||||||
@@ -30,6 +31,7 @@ module.exports = async (ctx) => {
|
|||||||
pubDate: new Date(`2019-3-1`).toUTCString(),
|
pubDate: new Date(`2019-3-1`).toUTCString(),
|
||||||
link: `https://github.com/DIYgod/RSSHub/issues/0`,
|
link: `https://github.com/DIYgod/RSSHub/issues/0`,
|
||||||
author: `DIYgod0`,
|
author: `DIYgod0`,
|
||||||
|
category: ['Category0', 'Category1', 'Category2'],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
} else if (ctx.params.id === 'long') {
|
} else if (ctx.params.id === 'long') {
|
||||||
|
|||||||
@@ -83,6 +83,28 @@ describe('filter', () => {
|
|||||||
expect(parsed.items[1].title).toBe('Title5');
|
expect(parsed.items[1].title).toBe('Title5');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it(`filter_category`, async () => {
|
||||||
|
const response = await request.get('/test/filter?filter_category=Category0|Category1');
|
||||||
|
const parsed = await parser.parseString(response.text);
|
||||||
|
expect(parsed.items.length).toBe(2);
|
||||||
|
expect(parsed.items[0].title).toBe('Filter Title1');
|
||||||
|
expect(parsed.items[1].title).toBe('Filter Title2');
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`filter_category filter_case_sensitive default`, async () => {
|
||||||
|
const response = await request.get('/test/filter?filter_category=category0|category1');
|
||||||
|
const parsed = await parser.parseString(response.text);
|
||||||
|
expect(parsed.items.length).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`filter_category filter_case_sensitive=false`, async () => {
|
||||||
|
const response = await request.get('/test/filter?filter_category=category0|category1&filter_case_sensitive=false');
|
||||||
|
const parsed = await parser.parseString(response.text);
|
||||||
|
expect(parsed.items.length).toBe(2);
|
||||||
|
expect(parsed.items[0].title).toBe('Filter Title1');
|
||||||
|
expect(parsed.items[1].title).toBe('Filter Title2');
|
||||||
|
});
|
||||||
|
|
||||||
it(`filter_time`, async () => {
|
it(`filter_time`, async () => {
|
||||||
const response = await request.get('/test/current_time?filter_time=25');
|
const response = await request.get('/test/current_time?filter_time=25');
|
||||||
const parsed = await parser.parseString(response.text);
|
const parsed = await parser.parseString(response.text);
|
||||||
@@ -185,6 +207,33 @@ describe('filter', () => {
|
|||||||
expect(parsed.items[2].title).toBe('Title3');
|
expect(parsed.items[2].title).toBe('Title3');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it(`filterout_category`, async () => {
|
||||||
|
const response = await request.get('/test/filter?filterout_category=Category0|Category1');
|
||||||
|
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_category filter_case_sensitive default`, async () => {
|
||||||
|
const response = await request.get('/test/filter?filterout_category=category0|category1');
|
||||||
|
const parsed = await parser.parseString(response.text);
|
||||||
|
expect(parsed.items.length).toBe(7);
|
||||||
|
expect(parsed.items[0].title).toBe('Filter Title1');
|
||||||
|
expect(parsed.items[1].title).toBe('Filter Title2');
|
||||||
|
expect(parsed.items[2].title).toBe('Title1');
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`filterout_category filter_case_sensitive=false`, async () => {
|
||||||
|
const response = await request.get('/test/filter?filterout_category=category0|category1&filter_case_sensitive=false');
|
||||||
|
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(`filter combination`, async () => {
|
it(`filter combination`, async () => {
|
||||||
const response = await request.get('/test/filter?filter_title=Filter&filter_description=Description1');
|
const response = await request.get('/test/filter?filter_title=Filter&filter_description=Description1');
|
||||||
const parsed = await parser.parseString(response.text);
|
const parsed = await parser.parseString(response.text);
|
||||||
|
|||||||
Reference in New Issue
Block a user