+
{activeView === 'dms' && activeDm === 'friends' ? (
) : (
@@ -741,7 +741,7 @@ export default function MainApp({ profile, setProfile, onLogout, updateState, si
{/* 1-on-1 Call View */}
{activeCall && (
data.status === 'pending_outgoing')
+ .map(([key]) => key);
+
+ const identityMsg = JSON.stringify({
+ type: 'identity',
+ displayName: this.displayName,
+ username: this.username,
+ avatar: this.avatar,
+ bio: this.bio,
+ connections: this.connections,
+ coreKey: this.coreKey,
+ topics: Array.from(this.joinedTopics),
+ pendingTargets
+ });
+
+ const payload = b4a.from(identityMsg);
+ for (const { conn } of this.peers.values()) {
+ try { conn.write(payload); } catch(e) {}
+ }
+ }
+
async initialize(seedHex, displayName, username, avatar = null, bio = '', connections = []) {
this.displayName = displayName;
this.username = (username || 'unknown').toLowerCase();
@@ -398,7 +423,23 @@ class P2PNetwork {
this.store.replicate(conn);
const peerKey = b4a.toString(info.publicKey, 'hex');
this.peers.set(peerKey, { conn, displayName: 'Unknown', username: 'unknown', avatar: null, bio: '', connections: [], coreKey: null });
- const identityMsg = JSON.stringify({ type: 'identity', displayName: this.displayName, username: this.username, avatar: this.avatar, bio: this.bio, connections: this.connections, coreKey: this.coreKey });
+
+ const pendingTargets = Object.entries(this.dms)
+ .filter(([_, data]) => data.status === 'pending_outgoing')
+ .map(([key]) => key);
+
+ const identityMsg = JSON.stringify({
+ type: 'identity',
+ displayName: this.displayName,
+ username: this.username,
+ avatar: this.avatar,
+ bio: this.bio,
+ connections: this.connections,
+ coreKey: this.coreKey,
+ topics: Array.from(this.joinedTopics),
+ pendingTargets
+ });
+
conn.write(b4a.from(identityMsg));
if (this.onPeerUpdate) this.onPeerUpdate(this.getPeerList());
conn.on('data', async (data) => handleData(this, peerKey, data, conn));
@@ -477,6 +518,9 @@ class P2PNetwork {
this.joinedTopics.add(topicHex);
const topic = b4a.from(topicHex, 'hex');
this.swarm.join(topic, { client: true, server: true });
+
+ this._broadcastIdentity();
+
if (!skipFlush) {
try { await this.swarm.flush(); } catch(e) {}
}
diff --git a/Peercord Source/src/p2p/modules/identity.js b/Peercord Source/src/p2p/modules/identity.js
index a640ce7..7474936 100644
--- a/Peercord Source/src/p2p/modules/identity.js
+++ b/Peercord Source/src/p2p/modules/identity.js
@@ -59,9 +59,5 @@ export function updateProfile(network, displayName, avatar, username, bio = '',
network._emitKnownProfiles();
if (!network.swarm) return;
-
- const identityMsg = JSON.stringify({ type: 'identity', displayName: network.displayName, username: network.username, avatar: network.avatar, bio: network.bio, connections: network.connections, coreKey: network.coreKey });
- const payload = b4a.from(identityMsg);
- for (const { conn } of network.peers.values()) conn.write(payload);
- network._emitMessages();
+ network._broadcastIdentity();
}
\ No newline at end of file
diff --git a/Peercord Source/src/p2p/modules/messaging.js b/Peercord Source/src/p2p/modules/messaging.js
index 72c79b0..d2bcbc2 100644
--- a/Peercord Source/src/p2p/modules/messaging.js
+++ b/Peercord Source/src/p2p/modules/messaging.js
@@ -7,32 +7,37 @@ export function getAllMessages(network) {
return Array.from(network.messages.values()).filter(m => {
const ch = m.payload.channel;
- if (ch && ch.length > 64 && ch[64] === '-') {
- const topicHex = ch.substring(0, 64);
- const chName = ch.substring(65);
- if (!joinedTopics.has(topicHex)) return false;
-
- const server = network.servers.find(s => s.topicHex === topicHex);
- if (server && network.myKey !== server.owner && network.myKey !== ADMIN_PUBLIC_KEY) {
- const userRoles = server.memberRoles?.[network.myKey] || [];
- const isServerAdmin = userRoles.some(rId => {
- const r = server.roles?.find(role => role.id === rId);
- return r && r.permissions.includes('admin');
- });
+ if (!m.recipient && ch) {
+ if (ch.length > 64 && ch[64] === '-') {
+ const topicHex = ch.substring(0, 64);
+ const chName = ch.substring(65);
+ if (!joinedTopics.has(topicHex)) return false;
- if (!isServerAdmin) {
- const channelPerms = server.channels?.permissions?.[chName];
- if (channelPerms && channelPerms.length > 0) {
- const hasChannelAccess = userRoles.some(rId => channelPerms.includes(rId));
- if (!hasChannelAccess) return false;
- }
-
- const hasReadPerm = userRoles.some(rId => {
+ const server = network.servers.find(s => s.topicHex === topicHex);
+ if (server && network.myKey !== server.owner && network.myKey !== ADMIN_PUBLIC_KEY) {
+ const userRoles = server.memberRoles?.[network.myKey] || [];
+ const isServerAdmin = userRoles.some(rId => {
const r = server.roles?.find(role => role.id === rId);
- return r && r.permissions.includes('read_messages');
+ return r && r.permissions.includes('admin');
});
- if (!hasReadPerm && server.roles && server.roles.length > 0) return false;
+
+ if (!isServerAdmin) {
+ const channelPerms = server.channels?.permissions?.[chName];
+ if (channelPerms && channelPerms.length > 0) {
+ const hasChannelAccess = userRoles.some(rId => channelPerms.includes(rId));
+ if (!hasChannelAccess) return false;
+ }
+
+ const hasReadPerm = userRoles.some(rId => {
+ const r = server.roles?.find(role => role.id === rId);
+ return r && r.permissions.includes('read_messages');
+ });
+ if (!hasReadPerm && server.roles && server.roles.length > 0) return false;
+ }
}
+ } else if (ch.length === 64) {
+ // Group chat: Filter out messages for group chats we are not in
+ if (!joinedTopics.has(ch)) return false;
}
}
return true;
@@ -352,50 +357,61 @@ export async function processMessage(network, msg) {
}
if (type === 'chat' || type === 'file') {
- let canAccept = true;
+ let canAccept = false;
+
if (channel && channel.length > 64 && channel[64] === '-') {
const topicHex = channel.substring(0, 64);
const chName = channel.substring(65);
const server = network.servers.find(s => s.topicHex === topicHex);
- if (server && msg.sender !== server.owner && msg.sender !== ADMIN_PUBLIC_KEY) {
- const userRoles = server.memberRoles?.[msg.sender] || [];
- const isServerAdmin = userRoles.some(rId => {
- const r = server.roles?.find(role => role.id === rId);
- return r && r.permissions.includes('admin');
- });
-
- if (!isServerAdmin) {
- const channelPerms = server.channels?.permissions?.[chName];
- if (channelPerms && channelPerms.length > 0) {
- const hasChannelAccess = userRoles.some(rId => channelPerms.includes(rId));
- if (!hasChannelAccess) canAccept = false;
- }
+
+ if (server) {
+ canAccept = true;
+ if (msg.sender !== server.owner && msg.sender !== ADMIN_PUBLIC_KEY) {
+ const userRoles = server.memberRoles?.[msg.sender] || [];
+ const isServerAdmin = userRoles.some(rId => {
+ const r = server.roles?.find(role => role.id === rId);
+ return r && r.permissions.includes('admin');
+ });
- if (canAccept) {
- const channelSendPerms = server.channels?.send_permissions?.[chName];
- if (channelSendPerms && channelSendPerms.length > 0) {
- const hasChannelSendAccess = userRoles.some(rId => channelSendPerms.includes(rId));
- if (!hasChannelSendAccess) canAccept = false;
+ if (!isServerAdmin) {
+ const channelPerms = server.channels?.permissions?.[chName];
+ if (channelPerms && channelPerms.length > 0) {
+ const hasChannelAccess = userRoles.some(rId => channelPerms.includes(rId));
+ if (!hasChannelAccess) canAccept = false;
}
- }
-
- if (canAccept) {
- const hasSendPerm = userRoles.some(rId => {
- const r = server.roles?.find(role => role.id === rId);
- return r && r.permissions.includes('send_messages');
- });
- if (!hasSendPerm && server.roles && server.roles.length > 0) canAccept = false;
-
- if (type === 'file') {
- const hasFilePerm = userRoles.some(rId => {
+
+ if (canAccept) {
+ const channelSendPerms = server.channels?.send_permissions?.[chName];
+ if (channelSendPerms && channelSendPerms.length > 0) {
+ const hasChannelSendAccess = userRoles.some(rId => channelSendPerms.includes(rId));
+ if (!hasChannelSendAccess) canAccept = false;
+ }
+ }
+
+ if (canAccept) {
+ const hasSendPerm = userRoles.some(rId => {
const r = server.roles?.find(role => role.id === rId);
- return r && r.permissions.includes('send_files');
+ return r && r.permissions.includes('send_messages');
});
- if (!hasFilePerm && server.roles && server.roles.length > 0) canAccept = false;
+ if (!hasSendPerm && server.roles && server.roles.length > 0) canAccept = false;
+
+ if (type === 'file') {
+ const hasFilePerm = userRoles.some(rId => {
+ const r = server.roles?.find(role => role.id === rId);
+ return r && r.permissions.includes('send_files');
+ });
+ if (!hasFilePerm && server.roles && server.roles.length > 0) canAccept = false;
+ }
}
}
}
}
+ } else if (channel && channel.length === 64) {
+ // Group chat: Only accept if we are actually in this group chat
+ const gc = network.servers.find(s => s.topicHex === channel && s.isGroupChat);
+ if (gc) {
+ canAccept = true;
+ }
}
if (canAccept && !network.deletedMessages.has(id) && !network.messages.has(id)) {
@@ -459,6 +475,7 @@ export async function sendDMRequest(network, targetKey, profile) {
await network.db.put('dm:' + targetKey, network.dms[targetKey]);
if (network.onDMsUpdate) network.onDMsUpdate({ ...network.dms });
await _appendEncryptedMessage(network, targetKey, { type: 'dm_request', profile: { displayName: network.displayName, username: network.username, avatar: network.avatar, bio: network.bio, connections: network.connections } });
+ network._broadcastIdentity();
}
export async function acceptDMRequest(network, targetKey) {
@@ -468,6 +485,7 @@ export async function acceptDMRequest(network, targetKey) {
if (network.onDMsUpdate) network.onDMsUpdate({ ...network.dms });
}
await _appendEncryptedMessage(network, targetKey, { type: 'dm_accept' });
+ network._broadcastIdentity();
}
export async function sendMessage(network, channel, text, replyTo = null) {
@@ -493,7 +511,9 @@ export async function sendReaction(network, targetId, emoji, isDM = false, targe
export function sendEphemeral(network, payload) {
if (!network.swarm) return;
const msg = b4a.from(JSON.stringify({ type: 'ephemeral', payload }));
- for (const { conn } of network.peers.values()) conn.write(msg);
+ for (const { conn } of network.peers.values()) {
+ try { conn.write(msg); } catch(e) {}
+ }
}
export function sendOffline(network) { sendEphemeral(network, { type: 'offline' }); }