You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
session-desktop/ts/opengroup/opengroupV2/JoinOpenGroupV2.ts

122 lines
4.2 KiB
TypeScript

import { allowOnlyOneAtATime } from '../../../js/modules/loki_primitives';
import {
getV2OpenGroupRoomByRoomId,
OpenGroupV2Room,
} from '../../data/opengroups';
import { ConversationModel } from '../../models/conversation';
import { ConversationController } from '../../session/conversations';
import { PromiseUtils } from '../../session/utils';
import { forceSyncConfigurationNowIfNeeded } from '../../session/utils/syncUtils';
import { prefixify } from '../utils/OpenGroupUtils';
import { attemptConnectionV2OneAtATime } from './OpenGroupManagerV2';
const protocolRegex = '(https?://)?';
const hostnameRegex =
'(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]).)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9-]*[A-Za-z0-9])';
const portRegex = '(:[0-9]+)?';
// roomIds allows between 2 and 64 of '0-9' or 'a-z' or '_' chars
const roomIdRegex = '[0-9a-z_]{2,64}';
const publicKeyRegex = '[0-9a-z]{64}';
const publicKeyParam = 'public_key=';
const openGroupV2CompleteURLRegex = new RegExp(
`^${protocolRegex}${hostnameRegex}${portRegex}/${roomIdRegex}\\?${publicKeyParam}${publicKeyRegex}$`,
'gm'
);
// Inputs that should work:
// https://sessionopengroup.co/main?public_key=658d29b91892a2389505596b135e76a53db6e11d613a51dbd3d0816adffb231c
// http://sessionopengroup.co/main?public_key=658d29b91892a2389505596b135e76a53db6e11d613a51dbd3d0816adffb231c
// sessionopengroup.co/main?public_key=658d29b91892a2389505596b135e76a53db6e11d613a51dbd3d0816adffb231c (does NOT go to HTTPS)
// https://143.198.213.225:443/main?public_key=658d29b91892a2389505596b135e76a53db6e11d613a51dbd3d0816adffb231c
// 143.198.213.255:80/main?public_key=658d29b91892a2389505596b135e76a53db6e11d613a51dbd3d0816adffb231c
export function parseOpenGroupV2(
urlWithPubkey: string
): OpenGroupV2Room | undefined {
const lowerCased = urlWithPubkey.toLowerCase();
try {
if (!openGroupV2CompleteURLRegex.test(lowerCased)) {
throw new Error('regex fail');
}
// prefix the URL if it does not have a prefix
const prefixedUrl = prefixify(lowerCased);
// new URL fails if the protocol is not explicit
const url = new URL(prefixedUrl);
let serverUrl = `${url.protocol}//${url.host}`;
if (url.port) {
serverUrl += `:${url.port}`;
}
const room: OpenGroupV2Room = {
serverUrl,
roomId: url.pathname.slice(1), // remove first '/'
serverPublicKey: url.search.slice(publicKeyParam.length + 1), // remove the '?' and the 'public_key=' header
};
return room;
} catch (e) {
window.log.error('Invalid Opengroup v2 join URL:', lowerCased);
}
return undefined;
}
/**
* Join an open group using the v2 logic.
*
* If you only have an string with all details in it, use parseOpenGroupV2() to extract and check the URL is valid
*
* @param server The server URL to join, defaults to https if protocol is not set
* @param room The room id to join
* @param publicKey The server publicKey. It comes from the joining link. (or is already here for the default open group server)
*/
export async function joinOpenGroupV2(
room: OpenGroupV2Room,
fromSyncMessage: boolean = false
): Promise<void> {
if (
!room.serverUrl ||
!room.roomId ||
room.roomId.length < 2 ||
!room.serverPublicKey
) {
return;
}
const serverUrl = room.serverUrl.toLowerCase();
const roomId = room.roomId.toLowerCase();
const publicKey = room.serverPublicKey.toLowerCase();
const prefixedServer = prefixify(serverUrl);
const alreadyExist = await getV2OpenGroupRoomByRoomId(serverUrl, roomId);
//FIXME audric
// if (alreadyExist) {
// window.log.warn('Skipping join opengroupv2: already exists');
// return;
// }
// Try to connect to server
try {
const conversation = await PromiseUtils.timeout(
attemptConnectionV2OneAtATime(prefixedServer, roomId, publicKey),
20000
);
if (!conversation) {
window.log.warn('Failed to join open group v2');
throw new Error(window.i18n('connectToServerFail'));
}
// here we managed to connect to the group.
// if this is not a Sync Message, we should trigger one
if (!fromSyncMessage) {
await forceSyncConfigurationNowIfNeeded();
}
} catch (e) {
window.log.error('Could not join open group v2', e);
throw new Error(e);
}
}