From de28a9ad5f69f8a150d3424f50cedaf02d540bd1 Mon Sep 17 00:00:00 2001 From: Hongbo Wu Date: Mon, 18 Mar 2024 18:41:14 +0800 Subject: [PATCH] fix bug --- packages/api/src/jobs/trigger_rule.ts | 4 +- packages/api/src/services/library_item.ts | 77 +++++++++++++---------- 2 files changed, 47 insertions(+), 34 deletions(-) diff --git a/packages/api/src/jobs/trigger_rule.ts b/packages/api/src/jobs/trigger_rule.ts index f94e3c37a..8a532eb07 100644 --- a/packages/api/src/jobs/trigger_rule.ts +++ b/packages/api/src/jobs/trigger_rule.ts @@ -1,9 +1,9 @@ -import { filter } from '@omnivore/liqe' import { ReadingProgressDataSource } from '../datasources/reading_progress_data_source' import { LibraryItemState } from '../entity/library_item' import { Rule, RuleAction, RuleActionType, RuleEventType } from '../entity/rule' import { addLabelsToLibraryItem } from '../services/labels' import { + filterItemEvents, ItemEvent, softDeleteLibraryItem, updateLibraryItem, @@ -112,7 +112,7 @@ const triggerActions = async ( try { const ast = parseSearchQuery(rule.filter) // filter library item by rule filter - const results = filter(ast, [data]) + const results = filterItemEvents(ast, [data]) if (results.length === 0) { logger.info(`No items found for rule ${rule.id}`) continue diff --git a/packages/api/src/services/library_item.ts b/packages/api/src/services/library_item.ts index dcea18b29..2a0b2de68 100644 --- a/packages/api/src/services/library_item.ts +++ b/packages/api/src/services/library_item.ts @@ -878,7 +878,8 @@ export const updateLibraryItemReadingProgress = async ( userId: string, bottomPercent: number, topPercent: number | null = null, - anchorIndex: number | null = null + anchorIndex: number | null = null, + pubsub = createPubSubClient() ): Promise => { // If we have a top percent, we only save it if it's greater than the current top percent // or set to zero if the top percent is zero. @@ -925,6 +926,13 @@ export const updateLibraryItemReadingProgress = async ( } const updatedItem = result[0][0] + await pubsub.entityUpdated( + EntityType.PAGE, + updatedItem, + userId, + id + ) + return updatedItem } @@ -1330,24 +1338,32 @@ export const filterItemEvents = ( const { field, expression } = ast - if (field.type === 'ImplicitField') { - // TODO: Implement full text search - throw new Error('Full text search is not supported.') - } if (expression.type !== 'LiteralExpression') { // ignore empty values throw new Error('Expected a literal expression.') } - const value = expression.value?.toString() - if (!value) { + const lowercasedValue = expression.value?.toString().toLowerCase() + + if (field.type === 'ImplicitField') { + if (!lowercasedValue) { + return true + } + + // TODO: Implement full text search + return event.readableContent + ?.toString() + ?.match(new RegExp(lowercasedValue, 'i')) + } + + if (!lowercasedValue) { // ignore empty values throw new Error('Expected a non-empty value.') } switch (field.name.toLowerCase()) { case 'in': { - switch (value.toLowerCase()) { + switch (lowercasedValue) { case InFilter.ALL: return true case InFilter.ARCHIVE: @@ -1355,12 +1371,15 @@ export const filterItemEvents = ( case InFilter.TRASH: return event.state === LibraryItemState.Deleted default: - return event.state === LibraryItemState.Succeeded + return ( + event.state != LibraryItemState.Archived && + event.state != LibraryItemState.Deleted + ) } } case 'is': { - switch (value.toLowerCase()) { + switch (lowercasedValue) { case ReadFilter.READ: return ( event.readingProgressBottomPercent && @@ -1378,15 +1397,15 @@ export const filterItemEvents = ( event.readingProgressBottomPercent < 2 ) default: - throw new Error(`Unexpected keyword: ${value}`) + throw new Error(`Unexpected keyword: ${lowercasedValue}`) } } case 'type': { - return event.itemType?.toString().toLowerCase() === value.toLowerCase() + return event.itemType?.toString().toLowerCase() === lowercasedValue } case 'label': { const labels = event.labelNames as string[] - const labelsToTest = value.toLowerCase().split(',') + const labelsToTest = lowercasedValue.split(',') return labelsToTest.some((label) => { const hasWildcard = label.includes('*') if (hasWildcard) { @@ -1397,14 +1416,14 @@ export const filterItemEvents = ( }) } case 'has': - return !testNo(value, event) + return !testNo(lowercasedValue, event) case 'read': case 'updated': case 'published': { let startDate: Date | undefined let endDate: Date | undefined // check for special date filters - switch (value.toLowerCase()) { + switch (lowercasedValue) { case 'today': startDate = DateTime.local().startOf('day').toJSDate() break @@ -1422,7 +1441,7 @@ export const filterItemEvents = ( break default: { // check for date ranges - const [start, end] = value.split('..') + const [start, end] = lowercasedValue.split('..') // validate date if (start && start !== '*') { startDate = new Date(start) @@ -1458,7 +1477,7 @@ export const filterItemEvents = ( // get camel case column name const key = camelCase(columnName) as 'subscription' | 'itemLanguage' - return event[key]?.toString().toLowerCase() === value.toLowerCase() + return event[key]?.toString().toLowerCase() === lowercasedValue } // match filters case 'author': @@ -1475,10 +1494,10 @@ export const filterItemEvents = ( | 'siteName' // TODO: Implement full text search - return event[key]?.toString().match(new RegExp(value, 'i')) + return event[key]?.toString().match(new RegExp(lowercasedValue, 'i')) } case 'includes': { - const ids = value.split(',') + const ids = lowercasedValue.split(',') if (!ids || ids.length === 0) { throw new Error('Expected ids') } @@ -1486,7 +1505,7 @@ export const filterItemEvents = ( return event.id && ids.includes(event.id.toString()) } case 'recommendedby': { - if (value === '*') { + if (lowercasedValue === '*') { // select all if * is provided return event.recommenderNames && event.recommenderNames.length > 0 } @@ -1494,12 +1513,12 @@ export const filterItemEvents = ( return ( event.recommenderNames && (event.recommenderNames as string[]).some( - (name) => name.toLowerCase() === value.toLowerCase() + (name) => name.toLowerCase() === lowercasedValue ) ) } case 'no': - return testNo(value, event) + return testNo(lowercasedValue, event) case 'use': case 'mode': case 'event': @@ -1508,12 +1527,12 @@ export const filterItemEvents = ( case 'readposition': case 'wordscount': { const operatorRegex = /([<>]=?)/ - const operator = value.match(operatorRegex)?.[0] + const operator = lowercasedValue.match(operatorRegex)?.[0] if (!operator) { throw new Error('Expected operator') } - const newValue = value.replace(operatorRegex, '') + const newValue = lowercasedValue.replace(operatorRegex, '') const intValue = parseInt(newValue, 10) const column = getColumnName(field.name) @@ -1536,13 +1555,7 @@ export const filterItemEvents = ( } } default: - // TODO: Implement full text search return false - // treat unknown fields as implicit fields - // return serializeImplicitField({ - // ...expression, - // value: `${field.name}:${value}`, - // }) } } @@ -1555,8 +1568,8 @@ export const filterItemEvents = ( if (ast.type === 'UnaryOperator') { const removeRows = filterItemEvents(ast.operand, events) - return events.filter((row) => { - return !removeRows.includes(row) + return events.filter((event) => { + return !removeRows.includes(event) }) }