(opts: MessageSearchOptions)
| 412 | }; |
| 413 | export namespace Search { |
| 414 | export async function searchMessages(opts: MessageSearchOptions) { |
| 415 | const results = await elastic.searchMessages(opts); |
| 416 | const messagesWithAuthors = await findManyMessagesWithAuthors( |
| 417 | results.map((r) => r.id!), |
| 418 | ); |
| 419 | // TODO: Include w/ query above |
| 420 | const [servers, channels] = await Promise.all([ |
| 421 | findManyServersById(messagesWithAuthors.map((m) => m.serverId)), |
| 422 | findManyChannelsById( |
| 423 | messagesWithAuthors.flatMap((m) => |
| 424 | m.parentChannelId ? [m.channelId, m.parentChannelId] : [m.channelId], |
| 425 | ), |
| 426 | ), |
| 427 | ]); |
| 428 | const serverLookup = new Map(servers.map((s) => [s.id, s])); |
| 429 | const channelLookup = new Map(channels.map((c) => [c.id, c])); |
| 430 | const resultsLookup = new Map(results.map((r) => [r.id, r])); |
| 431 | |
| 432 | return messagesWithAuthors |
| 433 | .map((m): SearchResult | null => { |
| 434 | const channel = channelLookup.get(m.parentChannelId ?? m.channelId); |
| 435 | const server = serverLookup.get(m.serverId); |
| 436 | const thread = m.parentChannelId |
| 437 | ? channelLookup.get(m.channelId) |
| 438 | : undefined; |
| 439 | if (!channel || !server) { |
| 440 | return null; |
| 441 | } |
| 442 | if (!channel.flags.indexingEnabled) { |
| 443 | return null; |
| 444 | } |
| 445 | return { |
| 446 | message: m, |
| 447 | channel, |
| 448 | score: resultsLookup.get(m.id)!.score ?? 0, |
| 449 | server: server, |
| 450 | thread, |
| 451 | }; |
| 452 | }) |
| 453 | .filter((res) => res != null && res.server.kickedTime === null) |
| 454 | .sort((a, b) => b!.score - a!.score) as SearchResult[]; |
| 455 | } |
| 456 | |
| 457 | export function indexMessageForSearch(messages: BaseMessageWithRelations[]) { |
| 458 | return elastic.bulkUpsertMessages( |
nothing calls this directly
no test coverage detected