|
|
|
@ -1,7 +1,17 @@
|
|
|
|
|
/* eslint-disable no-await-in-loop */
|
|
|
|
|
/* eslint-disable more/no-then */
|
|
|
|
|
/* eslint-disable @typescript-eslint/no-misused-promises */
|
|
|
|
|
import { compact, concat, difference, flatten, last, sample, toNumber, uniqBy } from 'lodash';
|
|
|
|
|
import {
|
|
|
|
|
compact,
|
|
|
|
|
concat,
|
|
|
|
|
difference,
|
|
|
|
|
flatten,
|
|
|
|
|
isEmpty,
|
|
|
|
|
last,
|
|
|
|
|
sample,
|
|
|
|
|
toNumber,
|
|
|
|
|
uniqBy,
|
|
|
|
|
} from 'lodash';
|
|
|
|
|
import { Data, Snode } from '../../../data/data';
|
|
|
|
|
import { SignalService } from '../../../protobuf';
|
|
|
|
|
import * as Receiver from '../../../receiver/receiver';
|
|
|
|
@ -26,6 +36,7 @@ import { IncomingMessage } from '../../messages/incoming/IncomingMessage';
|
|
|
|
|
import { ed25519Str } from '../../onions/onionPath';
|
|
|
|
|
import { StringUtils, UserUtils } from '../../utils';
|
|
|
|
|
import { perfEnd, perfStart } from '../../utils/Performance';
|
|
|
|
|
import { NotFoundError } from '../../utils/errors';
|
|
|
|
|
import { LibSessionUtil } from '../../utils/libsession/libsession_utils';
|
|
|
|
|
import { SnodeNamespace, SnodeNamespaces } from './namespaces';
|
|
|
|
|
import { SnodeAPIRetrieve } from './retrieveRequest';
|
|
|
|
@ -349,7 +360,7 @@ export class SwarmPolling {
|
|
|
|
|
|
|
|
|
|
private async handleSharedConfigMessages(
|
|
|
|
|
userConfigMessagesMerged: Array<RetrieveMessageItem>,
|
|
|
|
|
returnAndKeepInMemory?: boolean
|
|
|
|
|
returnDisplayNameOnly?: boolean
|
|
|
|
|
): Promise<string> {
|
|
|
|
|
const extractedUserConfigMessage = compact(
|
|
|
|
|
userConfigMessagesMerged.map((m: RetrieveMessageItem) => {
|
|
|
|
@ -396,7 +407,7 @@ export class SwarmPolling {
|
|
|
|
|
`handleConfigMessagesViaLibSession of "${allDecryptedConfigMessages.length}" messages with libsession`
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (returnAndKeepInMemory) {
|
|
|
|
|
if (returnDisplayNameOnly) {
|
|
|
|
|
let displayName = '';
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
@ -421,14 +432,13 @@ export class SwarmPolling {
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
const userInfo = await UserConfigWrapperActions.getUserInfo();
|
|
|
|
|
window.log.debug(`WIP: [SwarmPolling] userInfo: ${JSON.stringify(userInfo)}`);
|
|
|
|
|
if (!userInfo) {
|
|
|
|
|
throw new Error('UserInfo not found');
|
|
|
|
|
}
|
|
|
|
|
displayName = userInfo.name;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
window.log.warn(
|
|
|
|
|
'[SwarmPolling] LibSessionUtil.initializeLibSessionUtilWrappers failed with',
|
|
|
|
|
'LibSessionUtil.initializeLibSessionUtilWrappers failed with',
|
|
|
|
|
e.message
|
|
|
|
|
);
|
|
|
|
|
} finally {
|
|
|
|
@ -653,11 +663,9 @@ export class SwarmPolling {
|
|
|
|
|
// return the cached value
|
|
|
|
|
return this.lastHashes[nodeEdKey][pubkey][namespace];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Only exposed as public for testing
|
|
|
|
|
*/
|
|
|
|
|
public async pollOnceForDisplayName(pubkey: PubKey): Promise<string> {
|
|
|
|
|
public async pollOnceForOurDisplayName(): Promise<string> {
|
|
|
|
|
try {
|
|
|
|
|
const pubkey = UserUtils.getOurPubKeyFromCache();
|
|
|
|
|
const polledPubkey = pubkey.key;
|
|
|
|
|
const swarmSnodes = await snodePool.getSwarmFor(polledPubkey);
|
|
|
|
|
|
|
|
|
@ -671,59 +679,42 @@ export class SwarmPolling {
|
|
|
|
|
toPollFrom = sample(notPolled) as Snode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let resultsFromUserProfile: RetrieveMessagesResultsBatched | null;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
resultsFromUserProfile = await SnodeAPIRetrieve.retrieveDisplayName(
|
|
|
|
|
const resultsFromUserProfile = await SnodeAPIRetrieve.retrieveDisplayName(
|
|
|
|
|
toPollFrom,
|
|
|
|
|
UserUtils.getOurPubKeyStrFromCache()
|
|
|
|
|
);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
if (e.message === ERROR_CODE_NO_CONNECT) {
|
|
|
|
|
if (window.inboxStore?.getState().onionPaths.isOnline) {
|
|
|
|
|
window.inboxStore?.dispatch(updateIsOnline(false));
|
|
|
|
|
}
|
|
|
|
|
} else if (!window.inboxStore?.getState().onionPaths.isOnline) {
|
|
|
|
|
window.inboxStore?.dispatch(updateIsOnline(true));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
window.log.warn(
|
|
|
|
|
`pollOnceForDisplayName of ${pubkey} namespace: SnodeNamespaces.UserProfile failed with: ${e.message}`
|
|
|
|
|
pubkey.key
|
|
|
|
|
);
|
|
|
|
|
resultsFromUserProfile = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// check if we just fetched the details from the config namespaces.
|
|
|
|
|
// If yes, merge them together and exclude them from the rest of the messages.
|
|
|
|
|
if (resultsFromUserProfile?.length) {
|
|
|
|
|
if (!resultsFromUserProfile?.length) {
|
|
|
|
|
throw new Error('resultsFromUserProfile is empty');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const userConfigMessages = resultsFromUserProfile
|
|
|
|
|
.filter(m => SnodeNamespace.isUserConfigNamespace(m.namespace))
|
|
|
|
|
.map(r => r.messages.messages);
|
|
|
|
|
|
|
|
|
|
const userConfigMessagesMerged = flatten(compact(userConfigMessages));
|
|
|
|
|
|
|
|
|
|
if (userConfigMessagesMerged.length) {
|
|
|
|
|
const displayName = await this.handleSharedConfigMessages(userConfigMessagesMerged, true);
|
|
|
|
|
return displayName;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return '';
|
|
|
|
|
if (!userConfigMessagesMerged.length) {
|
|
|
|
|
throw new Error('after merging there are no user config messages');
|
|
|
|
|
}
|
|
|
|
|
const displayName = await this.handleSharedConfigMessages(userConfigMessagesMerged, true);
|
|
|
|
|
|
|
|
|
|
public async pollForOurDisplayName(): Promise<string> {
|
|
|
|
|
if (!window.getGlobalOnlineStatus()) {
|
|
|
|
|
window?.log?.error('pollForOurDisplayName: offline');
|
|
|
|
|
// Very important to set up a new polling call so we do retry at some point
|
|
|
|
|
setTimeout(this.pollForOurDisplayName.bind(this), SWARM_POLLING_TIMEOUT.ACTIVE);
|
|
|
|
|
return '';
|
|
|
|
|
if (isEmpty(displayName)) {
|
|
|
|
|
throw new NotFoundError('Got a config message from network but without a displayName...');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const displayName = await this.pollOnceForDisplayName(UserUtils.getOurPubKeyFromCache());
|
|
|
|
|
window.log.debug(`WIP: [pollForOurDisplayName] displayName ${displayName}`);
|
|
|
|
|
window.log.debug(`WIP: [pollOnceForOurDisplayName] displayName ${displayName}`);
|
|
|
|
|
return displayName;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
window?.log?.warn('pollForOurDisplayName exception: ', e);
|
|
|
|
|
if (e.message === ERROR_CODE_NO_CONNECT) {
|
|
|
|
|
if (window.inboxStore?.getState().onionPaths.isOnline) {
|
|
|
|
|
window.inboxStore?.dispatch(updateIsOnline(false));
|
|
|
|
|
}
|
|
|
|
|
} else if (!window.inboxStore?.getState().onionPaths.isOnline) {
|
|
|
|
|
window.inboxStore?.dispatch(updateIsOnline(true));
|
|
|
|
|
}
|
|
|
|
|
window.log.debug(`WIP: [pollOnceForOurDisplayName] no displayName found`, e);
|
|
|
|
|
throw e;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|