diff --git a/js/modules/loki_app_dot_net_api.js b/js/modules/loki_app_dot_net_api.js index 942b850a0..7202cbfa1 100644 --- a/js/modules/loki_app_dot_net_api.js +++ b/js/modules/loki_app_dot_net_api.js @@ -1879,14 +1879,14 @@ class LokiPublicChannelAPI { // eslint-disable-next-line no-plusplus for (let index = 0; index < pendingMessages.length; index++) { if (this.running) { - log.info( - 'emitting pending public message', - pendingMessages[index].serverId, - 'on', - this.channelId, - 'at', - this.serverAPI.baseServerUrl - ); + // log.info( + // 'emitting pending public message', + // pendingMessages[index].serverId, + // 'on', + // this.channelId, + // 'at', + // this.serverAPI.baseServerUrl + // ); // eslint-disable-next-line no-await-in-loop window.NewReceiver.handlePublicMessage(pendingMessages[index]); } diff --git a/ts/components/session/LeftPaneMessageSection.tsx b/ts/components/session/LeftPaneMessageSection.tsx index 3eff90f9a..06c51d8e8 100644 --- a/ts/components/session/LeftPaneMessageSection.tsx +++ b/ts/components/session/LeftPaneMessageSection.tsx @@ -419,7 +419,7 @@ export class LeftPaneMessageSection extends React.Component { } // Already connected? - if (Boolean(await OpenGroup.getConversation(serverUrl))) { + if (OpenGroup.getConversation(serverUrl)) { ToastUtils.pushToastError( 'publicChatExists', window.i18n('publicChatExists') @@ -447,7 +447,7 @@ export class LeftPaneMessageSection extends React.Component { ); } this.setState({ loading: false }); - const openGroupConversation = await OpenGroup.getConversation(serverUrl); + const openGroupConversation = OpenGroup.getConversation(serverUrl); if (!openGroupConversation) { window.log.error( diff --git a/ts/models/conversation.ts b/ts/models/conversation.ts index df05fc977..a4f6fb45e 100644 --- a/ts/models/conversation.ts +++ b/ts/models/conversation.ts @@ -505,7 +505,9 @@ export class ConversationModel extends Backbone.Model { public async getUnreadCount() { window.log.warn('getUnreadCount is slow'); - return getUnreadCountByConversation(this.id); + const unreadCount = await getUnreadCountByConversation(this.id); + + return unreadCount; } public queueJob(callback: any) { diff --git a/ts/receiver/configMessage.ts b/ts/receiver/configMessage.ts new file mode 100644 index 000000000..8f1c187c4 --- /dev/null +++ b/ts/receiver/configMessage.ts @@ -0,0 +1,162 @@ +import _ from 'lodash'; +import { getItemById, hasSyncedInitialConfigurationItem } from '../data/data'; +import { SignalService } from '../protobuf'; +import { ConversationController } from '../session/conversations'; +import { OpenGroup } from '../session/types'; +import { UserUtils } from '../session/utils'; +import { toHex } from '../session/utils/String'; +import { configurationMessageReceived, trigger } from '../shims/events'; +import { removeFromCache } from './cache'; +import { handleNewClosedGroup } from './closedGroups'; +import { updateProfile } from './dataMessage'; +import { EnvelopePlus } from './types'; + +async function handleOurProfileUpdate( + sentAt: number | Long, + configMessage: SignalService.ConfigurationMessage, + ourPubkey: string +) { + const latestProfileUpdateTimestamp = UserUtils.getLastProfileUpdateTimestamp(); + if (!latestProfileUpdateTimestamp || sentAt > latestProfileUpdateTimestamp) { + window?.log?.info( + `Handling our profileUdpate ourLastUpdate:${latestProfileUpdateTimestamp}, envelope sent at: ${sentAt}` + ); + const { profileKey, profilePicture, displayName } = configMessage; + + const ourConversation = ConversationController.getInstance().get(ourPubkey); + if (!ourConversation) { + window.log.error('We need a convo with ourself at all times'); + return; + } + + if (profileKey?.length) { + window.log.info('Saving our profileKey from configuration message'); + // TODO not sure why we keep our profileKey in storage AND in our conversaio + window.textsecure.storage.put('profileKey', profileKey); + } + const lokiProfile = { + displayName, + profilePicture, + }; + await updateProfile(ourConversation, lokiProfile, profileKey); + UserUtils.setLastProfileUpdateTimestamp(_.toNumber(sentAt)); + trigger(configurationMessageReceived, displayName); + } +} + +async function handleGroupsAndContactsFromConfigMessage( + envelope: EnvelopePlus, + configMessage: SignalService.ConfigurationMessage +) { + const didWeHandleAConfigurationMessageAlready = + (await getItemById(hasSyncedInitialConfigurationItem))?.value || false; + if (didWeHandleAConfigurationMessageAlready) { + window?.log?.warn( + 'Dropping configuration change as we already handled one... ' + ); + return; + } + if (didWeHandleAConfigurationMessageAlready) { + window?.log?.warn( + 'Dropping configuration change as we already handled one... ' + ); + return; + } + + const numberClosedGroup = configMessage.closedGroups?.length || 0; + + window?.log?.warn( + `Received ${numberClosedGroup} closed group on configuration. Creating them... ` + ); + + await Promise.all( + configMessage.closedGroups.map(async c => { + const groupUpdate = new SignalService.DataMessage.ClosedGroupControlMessage( + { + type: SignalService.DataMessage.ClosedGroupControlMessage.Type.NEW, + encryptionKeyPair: c.encryptionKeyPair, + name: c.name, + admins: c.admins, + members: c.members, + publicKey: c.publicKey, + } + ); + try { + await handleNewClosedGroup(envelope, groupUpdate); + } catch (e) { + window?.log?.warn( + 'failed to handle a new closed group from configuration message' + ); + } + }) + ); + + const allOpenGroups = OpenGroup.getAllAlreadyJoinedOpenGroupsUrl(); + const numberOpenGroup = configMessage.openGroups?.length || 0; + + // Trigger a join for all open groups we are not already in. + // Currently, if you left an open group but kept the conversation, you won't rejoin it here. + for (let i = 0; i < numberOpenGroup; i++) { + const current = configMessage.openGroups[i]; + if (!allOpenGroups.includes(current)) { + window?.log?.info( + `triggering join of public chat '${current}' from ConfigurationMessage` + ); + void OpenGroup.join(current); + } + } + if (configMessage.contacts?.length) { + await Promise.all( + configMessage.contacts.map(async c => { + try { + if (!c.publicKey) { + return; + } + const contactConvo = await ConversationController.getInstance().getOrCreateAndWait( + toHex(c.publicKey), + 'private' + ); + const profile = { + displayName: c.name, + profilePictre: c.profilePicture, + }; + await updateProfile(contactConvo, profile, c.profileKey); + } catch (e) { + window?.log?.warn( + 'failed to handle a new closed group from configuration message' + ); + } + }) + ); + } +} + +export async function handleConfigurationMessage( + envelope: EnvelopePlus, + configurationMessage: SignalService.ConfigurationMessage +): Promise { + const ourPubkey = UserUtils.getOurPubKeyStrFromCache(); + if (!ourPubkey) { + return; + } + + if (envelope.source !== ourPubkey) { + window?.log?.info( + 'Dropping configuration change from someone else than us.' + ); + return removeFromCache(envelope); + } + + await handleOurProfileUpdate( + envelope.timestamp, + configurationMessage, + ourPubkey + ); + + await handleGroupsAndContactsFromConfigMessage( + envelope, + configurationMessage + ); + + await removeFromCache(envelope); +} diff --git a/ts/receiver/contentMessage.ts b/ts/receiver/contentMessage.ts index fda3a3afa..578b7511e 100644 --- a/ts/receiver/contentMessage.ts +++ b/ts/receiver/contentMessage.ts @@ -21,6 +21,7 @@ import { handleNewClosedGroup } from './closedGroups'; import { KeyPairRequestManager } from './keyPairRequestManager'; import { requestEncryptionKeyPair } from '../session/group'; import { configurationMessageReceived, trigger } from '../shims/events'; +import { handleConfigurationMessage } from './configMessage'; export async function handleContentMessage(envelope: EnvelopePlus) { try { @@ -530,153 +531,3 @@ async function handleTypingMessage( }); } } - -async function handleOurProfileUpdate( - sentAt: number | Long, - configMessage: SignalService.ConfigurationMessage, - ourPubkey: string -) { - const latestProfileUpdateTimestamp = UserUtils.getLastProfileUpdateTimestamp(); - if (!latestProfileUpdateTimestamp || sentAt > latestProfileUpdateTimestamp) { - window?.log?.info( - `Handling our profileUdpate ourLastUpdate:${latestProfileUpdateTimestamp}, envelope sent at: ${sentAt}` - ); - const { profileKey, profilePicture, displayName } = configMessage; - - const ourConversation = ConversationController.getInstance().get(ourPubkey); - if (!ourConversation) { - window.log.error('We need a convo with ourself at all times'); - return; - } - - if (profileKey?.length) { - window.log.info('Saving our profileKey from configuration message'); - // TODO not sure why we keep our profileKey in storage AND in our conversaio - window.textsecure.storage.put('profileKey', profileKey); - } - const lokiProfile = { - displayName, - profilePicture, - }; - await updateProfile(ourConversation, lokiProfile, profileKey); - UserUtils.setLastProfileUpdateTimestamp(Lodash.toNumber(sentAt)); - trigger(configurationMessageReceived, displayName); - } -} - -async function handleGroupsAndContactsFromConfigMessage( - envelope: EnvelopePlus, - configMessage: SignalService.ConfigurationMessage -) { - const didWeHandleAConfigurationMessageAlready = - (await getItemById(hasSyncedInitialConfigurationItem))?.value || false; - if (didWeHandleAConfigurationMessageAlready) { - window?.log?.warn( - 'Dropping configuration change as we already handled one... ' - ); - return; - } - if (didWeHandleAConfigurationMessageAlready) { - window?.log?.warn( - 'Dropping configuration change as we already handled one... ' - ); - return; - } - - const numberClosedGroup = configMessage.closedGroups?.length || 0; - - window?.log?.warn( - `Received ${numberClosedGroup} closed group on configuration. Creating them... ` - ); - - await Promise.all( - configMessage.closedGroups.map(async c => { - const groupUpdate = new SignalService.DataMessage.ClosedGroupControlMessage( - { - type: SignalService.DataMessage.ClosedGroupControlMessage.Type.NEW, - encryptionKeyPair: c.encryptionKeyPair, - name: c.name, - admins: c.admins, - members: c.members, - publicKey: c.publicKey, - } - ); - try { - await handleNewClosedGroup(envelope, groupUpdate); - } catch (e) { - window?.log?.warn( - 'failed to handle a new closed group from configuration message' - ); - } - }) - ); - - const allOpenGroups = OpenGroup.getAllAlreadyJoinedOpenGroupsUrl(); - const numberOpenGroup = configMessage.openGroups?.length || 0; - - // Trigger a join for all open groups we are not already in. - // Currently, if you left an open group but kept the conversation, you won't rejoin it here. - for (let i = 0; i < numberOpenGroup; i++) { - const current = configMessage.openGroups[i]; - if (!allOpenGroups.includes(current)) { - window?.log?.info( - `triggering join of public chat '${current}' from ConfigurationMessage` - ); - void OpenGroup.join(current); - } - } - if (configMessage.contacts?.length) { - await Promise.all( - configMessage.contacts.map(async c => { - try { - if (!c.publicKey) { - return; - } - const contactConvo = await ConversationController.getInstance().getOrCreateAndWait( - toHex(c.publicKey), - 'private' - ); - const profile = { - displayName: c.name, - profilePictre: c.profilePicture, - }; - await updateProfile(contactConvo, profile, c.profileKey); - } catch (e) { - window?.log?.warn( - 'failed to handle a new closed group from configuration message' - ); - } - }) - ); - } -} - -export async function handleConfigurationMessage( - envelope: EnvelopePlus, - configurationMessage: SignalService.ConfigurationMessage -): Promise { - const ourPubkey = UserUtils.getOurPubKeyStrFromCache(); - if (!ourPubkey) { - return; - } - - if (envelope.source !== ourPubkey) { - window?.log?.info( - 'Dropping configuration change from someone else than us.' - ); - return removeFromCache(envelope); - } - - await handleOurProfileUpdate( - envelope.timestamp, - configurationMessage, - ourPubkey - ); - - await handleGroupsAndContactsFromConfigMessage( - envelope, - configurationMessage - ); - - await removeFromCache(envelope); -} diff --git a/ts/session/types/OpenGroup.ts b/ts/session/types/OpenGroup.ts index b06ba0afd..3a05ddb5f 100644 --- a/ts/session/types/OpenGroup.ts +++ b/ts/session/types/OpenGroup.ts @@ -120,7 +120,9 @@ export class OpenGroup { let conversationId; // Return OpenGroup if we're already connected - conversation = await OpenGroup.getConversation(prefixedServer); + conversation = OpenGroup.getConversation(prefixedServer); + console.warn(`Convo for ${prefixedServer}: ${conversation}`); + if (conversation) { conversationId = conversation?.cid; if (conversationId) { @@ -129,6 +131,11 @@ export class OpenGroup { channel: 1, conversationId, }); + } else { + console.warn( + 'NO conversationId = conversation?.cid', + conversation?.cid + ); } } @@ -167,9 +174,7 @@ export class OpenGroup { * @param server The server URL * @returns BackBone conversation model corresponding to the server if it exists, otherwise `undefined` */ - public static async getConversation( - server: string - ): Promise { + public static getConversation(server: string): ConversationModel | undefined { if (!OpenGroup.validate(server)) { return; } diff --git a/ts/test/session/unit/receiving/ConfigurationMessage_test.ts b/ts/test/session/unit/receiving/ConfigurationMessage_test.ts index a5874a44d..97f8aea68 100644 --- a/ts/test/session/unit/receiving/ConfigurationMessage_test.ts +++ b/ts/test/session/unit/receiving/ConfigurationMessage_test.ts @@ -1,7 +1,6 @@ // tslint:disable: no-implicit-dependencies import { SignalService } from '../../../../protobuf'; -import { handleConfigurationMessage } from '../../../../receiver/contentMessage'; import chai from 'chai'; import { ConfigurationMessage } from '../../../../session/messages/outgoing/content/ConfigurationMessage'; @@ -14,6 +13,7 @@ import * as data from '../../../../../ts/data/data'; import { EnvelopePlus } from '../../../../receiver/types'; import chaiAsPromised from 'chai-as-promised'; +import { handleConfigurationMessage } from '../../../../receiver/configMessage'; chai.use(chaiAsPromised as any); chai.should();