Support wildcards in the title search

This commit is contained in:
Fisto
2026-09-17 13:43:27 +02:00
parent 0fb93c4830
commit 8befc05591
8 changed files with 91 additions and 15 deletions
+27 -5
View File
@@ -187,6 +187,20 @@ export function normalizeTitleKey(title: string): string {
.replace(/\s+/g, " ");
}
/** Lowercase a title query and collapse punctuation, but keep `*` as a wildcard marker. */
export function normalizeTitleQuery(query: string): string {
return query
.toLowerCase()
.replace(/[^a-z0-9*]+/g, " ")
.trim()
.replace(/\s+/g, " ");
}
/** Escape LIKE metacharacters, then turn `*` into `%`. */
function titleLikePattern(value: string): string {
return value.replace(/[\\%_]/g, match => `\\${match}`).replace(/\*/g, "%");
}
const SCHEMA = `
CREATE TABLE IF NOT EXISTS messages (
id TEXT PRIMARY KEY,
@@ -803,14 +817,22 @@ export class ScrapeStore {
values.push(options.lengthGreaterThan);
}
if (options.titleQuery?.trim()) {
const query = normalizeTitleKey(options.titleQuery);
const query = normalizeTitleQuery(options.titleQuery);
if (options.titleExact) {
conditions.push("title_key LIKE ?");
values.push(`%${query}%`);
// One phrase, substring of the title; `*` still acts as a wildcard.
conditions.push("title_key LIKE ? ESCAPE '\\'");
values.push(`%${titleLikePattern(query)}%`);
} else {
for (const token of query.split(" ").filter(Boolean)) {
conditions.push("(' ' || COALESCE(title_key, '')) LIKE ?");
values.push(`% ${token}%`);
const pattern = titleLikePattern(token);
if (token.startsWith("*")) {
// Leading `*`: anywhere in a word, not just the start.
conditions.push("COALESCE(title_key, '') LIKE ? ESCAPE '\\'");
values.push(`%${pattern}%`);
} else {
conditions.push("(' ' || COALESCE(title_key, '')) LIKE ? ESCAPE '\\'");
values.push(`% ${pattern}%`);
}
}
}
}