feat(platform): forum archive search and show-archived toggle (v0.8.20)

Add searchForumPosts, setForumIncludeArchived, forum search scope in
_resolveSearchResults (fix channel db.get with guildId), guild search thread
titles, and pearcord-forum-search dependency.

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
Raven Scott
2026-05-22 00:13:51 -04:00
co-authored by Cursor
parent 24ba5b1f45
commit 7635295cfb
2 changed files with 85 additions and 10 deletions
+84 -10
View File
@@ -75,11 +75,13 @@ const {
const {
defaultThreadName,
groupThreadsByParent,
listForumPostsForParent,
isThreadChannel,
isForumChannel,
isAnnouncementChannel,
sortForumPosts
} = require('pearcord-threads')
const { forumPostHaystack } = require('pearcord-forum-search')
const {
classifyMessageLayout,
LAYOUT
@@ -321,6 +323,7 @@ class PearcordPlatform extends EventEmitter {
this.boosts = new PearcordBoosts({ storagePath: this.storagePath })
await this.boosts.ready()
this._forumTagFilter = null
this._forumIncludeArchived = false
this.guilds = await this.listGuilds()
void this._finishSessionStartup()
this.emit('user', user)
@@ -825,10 +828,32 @@ class PearcordPlatform extends EventEmitter {
setSearch ({ query, scope }) {
this._searchQuery = String(query || '').trim()
this._searchScope = scope === 'guild' ? 'guild' : 'channel'
if (scope === 'guild' || scope === 'forum') {
this._searchScope = scope
} else {
this._searchScope = 'channel'
}
return { query: this._searchQuery, scope: this._searchScope }
}
async _resolveSearchResults () {
const q = this._searchQuery
if (!q || !this.guild?.guild?.id) return []
if (this._searchScope === 'forum') {
const guildId = this.guild.guild.id
const ch = await this.db.get(COLLECTIONS.CHANNELS, {
guildId,
id: this.activeChannelId
})
if (!ch || !isForumChannel(ch)) return []
return this.searchForumPosts(guildId, ch.id, q)
}
if (this._searchScope === 'guild') {
return this.searchGuildMessages(this.guild.guild.id, q)
}
return []
}
setDiscoveryFilter ({ query, sort, minMembers, tag }) {
if (query !== undefined) this._discoveryFilter.query = String(query || '').trim()
if (sort === 'members' || sort === 'name' || sort === 'newest') {
@@ -868,6 +893,52 @@ class PearcordPlatform extends EventEmitter {
return { guildId, tags: row.discoveryTags }
}
setForumIncludeArchived (include) {
this._forumIncludeArchived = !!include
this.emit('forum-filter')
}
async searchForumPosts (guildId, forumChannelId, query, opts = {}) {
const q = String(query || '').trim().toLowerCase()
if (!q || !guildId || !forumChannelId) return []
const limit = opts.limit || 50
const includeArchived = opts.includeArchived !== false
const channels = await this.guild?.listChannels?.() || await this.db.find(COLLECTIONS.CHANNELS, { guildId })
const posts = listForumPostsForParent(channels, forumChannelId, { includeArchived })
const forumCh = channels.find((c) => c.id === forumChannelId)
const hits = []
for (const post of posts) {
const tags = this.forum ? await this.forum.getPostTags(guildId, post.id) : []
let content = ''
if (post.rootMessageId) {
const root = await this.db.get(COLLECTIONS.MESSAGES, {
channelId: post.id,
id: post.rootMessageId
})
content = root ? this._messagePlaintext(enrichMessageRow(root)) : ''
} else {
const rows = await this.db.find(COLLECTIONS.MESSAGES, { channelId: post.id })
if (rows[0]) content = this._messagePlaintext(enrichMessageRow(rows[0]))
}
const haystack = forumPostHaystack({
title: post.name,
content,
tags,
archived: post.archived
})
if (!haystack.includes(q)) continue
hits.push({
...post,
tags,
forumChannelId,
forumChannelName: forumCh?.name || 'forum',
searchHaystack: haystack,
snippet: String(content || '').slice(0, 160)
})
}
return hits.sort((a, b) => (b.createdAt || 0) - (a.createdAt || 0)).slice(0, limit)
}
async searchGuildMessages (guildId, query, opts = {}) {
const q = String(query || '').trim().toLowerCase()
if (!q || !guildId) return []
@@ -894,11 +965,16 @@ class PearcordPlatform extends EventEmitter {
if (!m?.id || seen.has(m.id)) return false
seen.add(m.id)
const enriched = enrichMessageRow(m)
const ch = channelById.get(m.channelId)
const hay = [
ch?.name || '',
String(enriched.content || ''),
enriched.hubMirror ? formatHubMirrorFallback(enriched.hubMirror) : '',
...(enriched.stickerNames || []).map((n) => `:${n}:`)
].join(' ').toLowerCase()
...(enriched.stickerNames || []).map((n) => `:${n}:`),
ch?.archived ? 'archived' : ''
]
.join(' ')
.toLowerCase()
return searchable.has(m.channelId) && hay.includes(q)
})
.sort((a, b) => b.createdAt - a.createdAt)
@@ -3754,7 +3830,9 @@ class PearcordPlatform extends EventEmitter {
const activeChannel = channels.find((c) => c.id === this.activeChannelId) || null
let forumPosts =
activeChannel && isForumChannel(activeChannel)
? sortForumPosts(threadsByParent[activeChannel.id] || [])
? listForumPostsForParent(channels, activeChannel.id, {
includeArchived: this._forumIncludeArchived
})
: []
let forumPaletteTags = []
let forumUsedTags = []
@@ -4021,12 +4099,8 @@ class PearcordPlatform extends EventEmitter {
stepUpUnlocked,
searchQuery: this._searchQuery,
searchScope: this._searchScope,
searchResults:
this._searchScope === 'guild' &&
this._searchQuery &&
this.guild?.guild?.id
? await this.searchGuildMessages(this.guild.guild.id, this._searchQuery)
: [],
forumIncludeArchived: this._forumIncludeArchived,
searchResults: await this._resolveSearchResults(),
contacts: this.contacts
? {
...(await this.listContacts()),
+1
View File
@@ -39,6 +39,7 @@
"pearcord-device-sync": "file:../pearcord-device-sync",
"pearcord-step-up": "file:../pearcord-step-up",
"pearcord-forum": "file:../pearcord-forum",
"pearcord-forum-search": "file:../pearcord-forum-search",
"pearcord-stage": "file:../pearcord-stage",
"pearcord-automod": "file:../pearcord-automod",
"pearcord-screen-share": "file:../pearcord-screen-share",