mirror of
https://github.com/omnivore-app/omnivore.git
synced 2026-03-11 08:54:26 +00:00
fallback to search query if implicit fields are in the filter
This commit is contained in:
parent
37459f64c7
commit
4c458c7118
2 changed files with 44 additions and 34 deletions
|
|
@ -1,10 +1,13 @@
|
|||
import { LiqeQuery } from '@omnivore/liqe'
|
||||
import { ReadingProgressDataSource } from '../datasources/reading_progress_data_source'
|
||||
import { LibraryItemState } from '../entity/library_item'
|
||||
import { LibraryItem, LibraryItemState } from '../entity/library_item'
|
||||
import { Rule, RuleAction, RuleActionType, RuleEventType } from '../entity/rule'
|
||||
import { addLabelsToLibraryItem } from '../services/labels'
|
||||
import {
|
||||
filterItemEvents,
|
||||
ItemEvent,
|
||||
RequiresSearchQueryError,
|
||||
searchLibraryItems,
|
||||
softDeleteLibraryItem,
|
||||
updateLibraryItem,
|
||||
} from '../services/library_item'
|
||||
|
|
@ -24,7 +27,7 @@ interface RuleActionObj {
|
|||
libraryItemId: string
|
||||
userId: string
|
||||
action: RuleAction
|
||||
data: ItemEvent
|
||||
data: ItemEvent | LibraryItem
|
||||
}
|
||||
type RuleActionFunc = (obj: RuleActionObj) => Promise<unknown>
|
||||
|
||||
|
|
@ -107,33 +110,52 @@ const triggerActions = async (
|
|||
const actionPromises: Promise<unknown>[] = []
|
||||
|
||||
for (const rule of rules) {
|
||||
let filteredData: ItemEvent
|
||||
let ast: LiqeQuery
|
||||
let results: (ItemEvent | LibraryItem)[]
|
||||
|
||||
try {
|
||||
const ast = parseSearchQuery(rule.filter)
|
||||
// filter library item by rule filter
|
||||
const results = filterItemEvents(ast, [data])
|
||||
if (results.length === 0) {
|
||||
logger.info(`No items found for rule ${rule.id}`)
|
||||
continue
|
||||
}
|
||||
|
||||
filteredData = results[0]
|
||||
ast = parseSearchQuery(rule.filter)
|
||||
} catch (error) {
|
||||
// failed to search for library items, mark rule as failed
|
||||
logger.error('Error parsing filter in rules', error)
|
||||
await markRuleAsFailed(rule.id, userId)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// filter library item by metadata
|
||||
try {
|
||||
results = filterItemEvents(ast, [data])
|
||||
} catch (error) {
|
||||
if (error instanceof RequiresSearchQueryError) {
|
||||
logger.info('Failed to filter items by metadata, running search query')
|
||||
// failed to filter items by metadata, run search query
|
||||
const searchResult = await searchLibraryItems(
|
||||
{
|
||||
query: `includes: ${libraryItemId} AND (${rule.filter})`,
|
||||
size: 1,
|
||||
},
|
||||
userId
|
||||
)
|
||||
results = searchResult.libraryItems
|
||||
} else {
|
||||
logger.error('Error filtering item events', error)
|
||||
await markRuleAsFailed(rule.id, userId)
|
||||
|
||||
continue
|
||||
}
|
||||
}
|
||||
if (results.length === 0) {
|
||||
logger.info(`No items found for rule ${rule.id}`)
|
||||
continue
|
||||
}
|
||||
|
||||
for (const action of rule.actions) {
|
||||
const actionFunc = getRuleAction(action.type)
|
||||
const actionObj: RuleActionObj = {
|
||||
libraryItemId,
|
||||
userId,
|
||||
action,
|
||||
data: filteredData,
|
||||
data: results[0],
|
||||
}
|
||||
|
||||
actionPromises.push(actionFunc(actionObj))
|
||||
|
|
|
|||
|
|
@ -43,6 +43,12 @@ export type UpdateItemEvent = Omit<
|
|||
IgnoredFields
|
||||
>
|
||||
|
||||
export class RequiresSearchQueryError extends Error {
|
||||
constructor() {
|
||||
super('Requires a search query')
|
||||
}
|
||||
}
|
||||
|
||||
enum ReadFilter {
|
||||
ALL = 'all',
|
||||
READ = 'read',
|
||||
|
|
@ -1328,7 +1334,7 @@ export const findLibraryItemIdsByLabelId = async (
|
|||
export const filterItemEvents = (
|
||||
ast: LiqeQuery,
|
||||
events: readonly ItemEvent[]
|
||||
): readonly ItemEvent[] => {
|
||||
): ItemEvent[] => {
|
||||
const testNo = (value: string, event: ItemEvent) => {
|
||||
const keywordRegexMap: Record<string, RegExp> = {
|
||||
highlightAnnotations: /^highlight(s)?$/i,
|
||||
|
|
@ -1364,25 +1370,7 @@ export const filterItemEvents = (
|
|||
const lowercasedValue = expression.value?.toString().toLowerCase()
|
||||
|
||||
if (field.type === 'ImplicitField') {
|
||||
if (!lowercasedValue) {
|
||||
return true
|
||||
}
|
||||
|
||||
const textFields = [
|
||||
'author',
|
||||
'title',
|
||||
'description',
|
||||
'note',
|
||||
'siteName',
|
||||
'readableContent',
|
||||
'originalUrl',
|
||||
]
|
||||
const text = textFields
|
||||
.map((field) => event[field as keyof ItemEvent])
|
||||
.join(' ')
|
||||
|
||||
// TODO: Implement full text search
|
||||
return text.match(new RegExp(lowercasedValue, 'i'))
|
||||
throw new RequiresSearchQueryError()
|
||||
}
|
||||
|
||||
if (!lowercasedValue) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue