fix(contacts): improve friend requests and relay DM channel invites
Use server+client ephemeral joins with longer flush for CONTACT_REQUEST delivery. Forward DM_CHANNEL_UPSERT to peers on the contacts mesh. Co-authored-by: Cursor <[email protected]>
This commit is contained in:
@@ -110,6 +110,12 @@ class PearcordContacts extends EventEmitter {
|
|||||||
return row
|
return row
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async sendDmChannelInvite (peerUserId, channel) {
|
||||||
|
if (!peerUserId || !channel?.id) return null
|
||||||
|
await this._gossipToPeer(peerUserId, RPC.DM_CHANNEL_UPSERT, channel)
|
||||||
|
return channel
|
||||||
|
}
|
||||||
|
|
||||||
async acceptRequest (peerUserId) {
|
async acceptRequest (peerUserId) {
|
||||||
const row = await this.get(peerUserId)
|
const row = await this.get(peerUserId)
|
||||||
if (!row || row.status !== CONTACT_STATUS.PENDING_IN) {
|
if (!row || row.status !== CONTACT_STATUS.PENDING_IN) {
|
||||||
@@ -231,6 +237,7 @@ class PearcordContacts extends EventEmitter {
|
|||||||
id: blocked?.id || id(),
|
id: blocked?.id || id(),
|
||||||
ownerId: this.userId,
|
ownerId: this.userId,
|
||||||
peerUserId: from,
|
peerUserId: from,
|
||||||
|
peerUsername: payload.fromUsername || null,
|
||||||
peerDisplayName: payload.fromDisplayName || payload.fromUsername || from.slice(0, 8),
|
peerDisplayName: payload.fromDisplayName || payload.fromUsername || from.slice(0, 8),
|
||||||
status: mutual ? CONTACT_STATUS.ACCEPTED : CONTACT_STATUS.PENDING_IN,
|
status: mutual ? CONTACT_STATUS.ACCEPTED : CONTACT_STATUS.PENDING_IN,
|
||||||
requestedAt: payload.at || now(),
|
requestedAt: payload.at || now(),
|
||||||
@@ -343,6 +350,10 @@ class PearcordContacts extends EventEmitter {
|
|||||||
this.emit('profile-cosmetic', payload)
|
this.emit('profile-cosmetic', payload)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if (method === RPC.DM_CHANNEL_UPSERT) {
|
||||||
|
this.emit('dm-channel', payload)
|
||||||
|
return
|
||||||
|
}
|
||||||
if (method === RPC.CONTACT_REQUEST) {
|
if (method === RPC.CONTACT_REQUEST) {
|
||||||
this.ingestRequest(payload).catch(() => {})
|
this.ingestRequest(payload).catch(() => {})
|
||||||
} else if (method === RPC.CONTACT_ACCEPT) {
|
} else if (method === RPC.CONTACT_ACCEPT) {
|
||||||
@@ -359,6 +370,10 @@ class PearcordContacts extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async simulateGossip (method, payload) {
|
async simulateGossip (method, payload) {
|
||||||
|
if (method === RPC.DM_CHANNEL_UPSERT) {
|
||||||
|
this.emit('dm-channel', payload)
|
||||||
|
return payload
|
||||||
|
}
|
||||||
if (method === RPC.PRESENCE_UPDATE) return this.ingestFriendPresence(payload)
|
if (method === RPC.PRESENCE_UPDATE) return this.ingestFriendPresence(payload)
|
||||||
if (method === RPC.PROFILE_COSMETIC_UPDATE) {
|
if (method === RPC.PROFILE_COSMETIC_UPDATE) {
|
||||||
this.emit('profile-cosmetic', payload)
|
this.emit('profile-cosmetic', payload)
|
||||||
@@ -413,13 +428,15 @@ class PearcordContacts extends EventEmitter {
|
|||||||
const persistent = this._friendTopics.has(topic)
|
const persistent = this._friendTopics.has(topic)
|
||||||
const wasEphemeral = this._ephemeralTopics.has(topic)
|
const wasEphemeral = this._ephemeralTopics.has(topic)
|
||||||
if (!persistent && !wasEphemeral) {
|
if (!persistent && !wasEphemeral) {
|
||||||
await this.swarm.join(buf, { server: false, client: true })
|
await this.swarm.join(buf, { server: true, client: true })
|
||||||
this._ephemeralTopics.add(topic)
|
this._ephemeralTopics.add(topic)
|
||||||
}
|
}
|
||||||
await this._flushSwarm()
|
await this._flushSwarm(6000)
|
||||||
await broadcastContactsGossip(this, method, payload)
|
await broadcastContactsGossip(this, method, payload)
|
||||||
if (!persistent && !wasEphemeral) {
|
if (!persistent && !wasEphemeral) {
|
||||||
await new Promise((r) => setTimeout(r, 350))
|
await new Promise((r) => setTimeout(r, 1200))
|
||||||
|
await broadcastContactsGossip(this, method, payload).catch(() => {})
|
||||||
|
await new Promise((r) => setTimeout(r, 400))
|
||||||
await this.swarm.leave(buf).catch(() => {})
|
await this.swarm.leave(buf).catch(() => {})
|
||||||
this._ephemeralTopics.delete(topic)
|
this._ephemeralTopics.delete(topic)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,12 +2,13 @@
|
|||||||
|
|
||||||
const Protomux = require('protomux')
|
const Protomux = require('protomux')
|
||||||
const b4a = require('b4a')
|
const b4a = require('b4a')
|
||||||
const { encodeRpc, decodeRpc } = require('pearcord-shared')
|
const { encodeRpc, decodeRpc, wireSwarmConnection } = require('pearcord-shared')
|
||||||
const { openWireChannel, wireReady } = require('pearcord-drive/mux-wire')
|
const { openWireChannel, wireReady } = require('pearcord-drive/mux-wire')
|
||||||
|
|
||||||
const CONTACTS_PROTOCOL = 'pearcord-contacts-v1'
|
const CONTACTS_PROTOCOL = 'pearcord-contacts-v1'
|
||||||
|
|
||||||
function attachContactsMesh (contacts, conn) {
|
function attachContactsMesh (contacts, conn) {
|
||||||
|
wireSwarmConnection(conn)
|
||||||
const mux = Protomux.from(conn)
|
const mux = Protomux.from(conn)
|
||||||
return openWireChannel(mux, {
|
return openWireChannel(mux, {
|
||||||
protocol: CONTACTS_PROTOCOL,
|
protocol: CONTACTS_PROTOCOL,
|
||||||
|
|||||||
Reference in New Issue
Block a user