Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/popular-cameras-guess.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---

Fixes an issue where searching messages by attachment description or title failed for non-ASCII characters, thereby enabling search across multiple languages.
29 changes: 23 additions & 6 deletions apps/meteor/server/lib/parseMessageSearchQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,17 @@ class MessageSearchQueryParser {
* Filter image tags
*/
private consumeLabel(text: string) {
return text.replace(/label:(\w+)/g, (_: string, tag: string) => {
return text.replace(/label:*"([^"]+)"|label:"?([^\s"]+[^"]?)"?/gu, (_match, quoted, unquoted) => {
const tag = quoted ?? unquoted;
Comment thread
kody-ai[bot] marked this conversation as resolved.
Outdated
Comment thread
kody-ai[bot] marked this conversation as resolved.
Outdated
if (!tag) {
return '';
}

this.query['attachments.0.labels'] = {
$regex: escapeRegExp(tag),
$regex: escapeRegExp(tag.trim()),
$options: 'i',
};

return '';
});
}
Expand All @@ -131,11 +137,17 @@ class MessageSearchQueryParser {
* Filter on description of messages.
*/
private consumeFileDescription(text: string) {
return text.replace(/file-desc:(\w+)/g, (_: string, tag: string) => {
return text.replace(/file-desc:"([^"]+)"|file-desc:"?([^\s"]+[^"]?)"?/gu, (_match, quoted, unquoted) => {
const tag = quoted ?? unquoted;
if (!tag) {
return '';
}

this.query['attachments.description'] = {
$regex: escapeRegExp(tag),
$regex: escapeRegExp(tag.trim()),
$options: 'i',
};

return '';
});
}
Expand All @@ -144,9 +156,14 @@ class MessageSearchQueryParser {
* Filter on title of messages.
*/
private consumeFileTitle(text: string) {
return text.replace(/file-title:(\w+)/g, (_: string, tag: string) => {
return text.replace(/file-title:"([^"]+)"|file-title:"?([^\s"]+[^"]?)"?/gu, (_match, quoted, unquoted) => {
const tag = quoted ?? unquoted;
if (!tag) {
return '';
}

this.query['attachments.title'] = {
$regex: escapeRegExp(tag),
$regex: escapeRegExp(tag.trim()),
$options: 'i',
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,109 @@ describe('parseMessageSearchQuery', () => {
query: { 'attachments.0.labels': { $regex: 'label2', $options: 'i' } },
options: { projection: {}, sort: { ts: -1 }, skip: 0, limit: 20 },
},
{
text: 'file-title:title',
query: { 'attachments.title': { $regex: 'title', $options: 'i' } },
options: { projection: {}, sort: { ts: -1 }, skip: 0, limit: 20 },
},
{
text: 'file-desc:description',
query: { 'attachments.description': { $regex: 'description', $options: 'i' } },
query: {
'attachments.description': { $regex: 'description', $options: 'i' },
},
options: { projection: {}, sort: { ts: -1 }, skip: 0, limit: 20 },
},
{
text: 'file-title:title',
query: { 'attachments.title': { $regex: 'title', $options: 'i' } },
text: 'file-desc:"description"',
query: {
'attachments.description': { $regex: 'description', $options: 'i' },
},
options: { projection: {}, sort: { ts: -1 }, skip: 0, limit: 20 },
},
{
text: 'file-title:"monthly report"',
query: {
'attachments.title': { $regex: 'monthly report', $options: 'i' },
},
options: { projection: {}, sort: { ts: -1 }, skip: 0, limit: 20 },
},
{
text: 'file-desc:отчет follow-up needed',
query: {
'attachments.description': { $regex: 'отчет', $options: 'i' },
'$text': { $search: 'follow-up needed' },
},
options: { projection: { score: { $meta: 'textScore' } }, sort: { ts: -1 }, skip: 0, limit: 20 },
},
{
text: 'file-title:"🚀 launch plan" notes later',
query: {
'attachments.title': { $regex: '🚀 launch plan', $options: 'i' },
'$text': { $search: 'notes later' },
},
options: { projection: { score: { $meta: 'textScore' } }, sort: { ts: -1 }, skip: 0, limit: 20 },
},
{
text: 'notes later file-title:"🚀 launch plan"',
query: {
'attachments.title': { $regex: '🚀 launch plan', $options: 'i' },
'$text': { $search: 'notes later' },
},
options: { projection: { score: { $meta: 'textScore' } }, sort: { ts: -1 }, skip: 0, limit: 20 },
},
{
text: 'file-desc:report2024 file-title:Q1-review pending',
query: {
'attachments.description': { $regex: 'report2024', $options: 'i' },
'attachments.title': { $regex: 'Q1\\-review', $options: 'i' },
'$text': { $search: 'pending' },
},
options: { projection: { score: { $meta: 'textScore' } }, sort: { ts: -1 }, skip: 0, limit: 20 },
},
{
text: 'file-desc:"中 文 测 试" file-title:"报 表" 其他内容',
query: {
'attachments.description': { $regex: '中 文 测 试', $options: 'i' },
'attachments.title': { $regex: '报 表', $options: 'i' },
'$text': { $search: '其他内容' },
},
options: { projection: { score: { $meta: 'textScore' } }, sort: { ts: -1 }, skip: 0, limit: 20 },
},
{
text: 'file-desc:отчет file-title:"финансовый план" завершено',
query: {
'attachments.description': { $regex: 'отчет', $options: 'i' },
'attachments.title': { $regex: 'финансовый план', $options: 'i' },
'$text': { $search: 'завершено' },
},
options: { projection: { score: { $meta: 'textScore' } }, sort: { ts: -1 }, skip: 0, limit: 20 },
},
{
text: 'file-title:"🔥 final version" confirm now',
query: {
'attachments.title': { $regex: '🔥 final version', $options: 'i' },
'$text': { $search: 'confirm now' },
},
options: { projection: { score: { $meta: 'textScore' } }, sort: { ts: -1 }, skip: 0, limit: 20 },
},
{
text: 'file-desc:"launch" from:username new plans',
query: {
'attachments.description': { $regex: 'launch', $options: 'i' },
'u.username': { $regex: 'username', $options: 'i' },
'$text': { $search: 'new plans' },
},
options: { projection: { score: { $meta: 'textScore' } }, sort: { ts: -1 }, skip: 0, limit: 20 },
},
{
text: 'mention:someone file-desc:"budget 💰" file update',
query: {
'attachments.description': { $regex: 'budget 💰', $options: 'i' },
'mentions.username': { $regex: 'someone', $options: 'i' },
'$text': { $search: 'file update' },
},
options: { projection: { score: { $meta: 'textScore' } }, sort: { ts: -1 }, skip: 0, limit: 20 },
},
{
text: 'before:01-01-2023',
query: { ts: { $lte: new Date(2023, 0, 1, utcOffset) } },
Expand Down