feat(platform): invite preview and guild create templates (Phase 663)

Add previewJoinInvite for join preview metadata and templateId channel
presets on createGuild for friends/club onboarding branches.

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
Raven Scott
2026-06-02 16:01:17 -04:00
co-authored by Cursor
parent c3caa74566
commit 6ff4def1ed
+63 -3
View File
@@ -4304,7 +4304,13 @@ class PearcordPlatform extends EventEmitter {
})
try {
if (query !== undefined) this._discoveryFilter.query = String(query || '').trim()
if (sort === 'members' || sort === 'name' || sort === 'newest') {
if (
sort === 'members' ||
sort === 'name' ||
sort === 'newest' ||
sort === 'active' ||
sort === 'size'
) {
this._discoveryFilter.sort = sort
}
if (minMembers !== undefined) {
@@ -13979,7 +13985,7 @@ class PearcordPlatform extends EventEmitter {
}
}
async createGuild ({ name, publicListing = true } = {}) {
async createGuild ({ name, publicListing = true, templateId = null } = {}) {
const user = this.identity.user
if (!user) throw new Error('register first')
const hadGuilds = this.guilds.length
@@ -14003,12 +14009,38 @@ class PearcordPlatform extends EventEmitter {
})
await this.guild.ready()
const result = await this.guild.create({ name })
if (templateId) {
const presets = {
friends: [{ name: 'memes', type: 'text' }],
club: [
{ name: 'announcements', type: 'text' },
{ name: 'off-topic', type: 'text' }
]
}
const preset = presets[templateId] || []
const existing = await this.guild.listChannels()
for (const ch of preset) {
if (
existing.some(
(c) => String(c.name).toLowerCase() === ch.name.toLowerCase()
)
) {
continue
}
await this.guild.createChannel({
name: ch.name,
type: ch.type,
parentId: null
})
}
}
this._wireGuild(this.guild)
await this._requestGuildMeshJoin({ source: 'guild-create', bounded: true })
await this._initGuildVoice(result.guild.id)
this.messages = new PearcordMessage({ authorId: user.id, db: this.db })
await this.messages.ready()
const text = result.channels.find((c) => c.type === 'text')
const channelsAfter = await this.guild.listChannels()
const text = channelsAfter.find((c) => c.type === 'text')
if (text) this.selectChannel(text.id)
this.guilds = await this.listGuilds()
if (this.slashCommands) {
@@ -14375,6 +14407,34 @@ class PearcordPlatform extends EventEmitter {
return out
}
async previewJoinInvite (code) {
const validated = validatePastedNavigationInput(code)
if (!validated.ok) {
return { ok: false, code: validated.code, message: pasteValidationToast(validated) }
}
const raw = validated.normalized
if (raw.toLowerCase().startsWith('pearcord://')) {
return { ok: false, code: 'deep_link', message: 'Open pearcord:// links from the join field to navigate.' }
}
const invite = await this.invite.resolve(raw)
if (!invite) {
return { ok: false, code: 'invalid_invite', message: 'Invite not found or expired.' }
}
const channelCount = (invite.channels || []).length
return {
ok: true,
preview: {
guildId: invite.guildId,
guildName: invite.guildName || 'Server',
topic: invite.topic || null,
memberCount: Math.max(1, channelCount || 1),
channelCount,
publicListing: invite.publicListing !== false,
expiresAt: invite.expiresAt || null
}
}
}
async joinInvite (code) {
const validated = validatePastedNavigationInput(code)
if (!validated.ok) {