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/session/apis/open_group_api/sogsv3/sogsV3Capabilities.ts

117 lines
3.7 KiB
TypeScript

import _, { isArray, isEmpty, isEqual, isObject } from 'lodash';
import { OnionSending } from '../../../onions/onionSend';
import { OpenGroupPollingUtils } from '../opengroupV2/OpenGroupPollingUtils';
import { OpenGroupData, OpenGroupV2Room } from '../../../../data/opengroups';
import AbortController, { AbortSignal } from 'abort-controller';
import { batchGlobalIsSuccess } from './sogsV3BatchPoll';
export const capabilitiesFetchForServer = async (
serverUrl: string,
serverPubKey: string,
abortSignal: AbortSignal
): Promise<Array<string> | null> => {
const endpoint = '/capabilities';
const method = 'GET';
const serverPubkey = serverPubKey;
const blinded = false; // for capabilities, blinding is always false as the request will fail if the server requires blinding
const capabilityHeaders = await OpenGroupPollingUtils.getOurOpenGroupHeaders(
serverPubkey,
endpoint,
method,
blinded,
null
);
if (!capabilityHeaders) {
return null;
}
const result = await OnionSending.sendJsonViaOnionV4ToSogs({
abortSignal,
blinded,
endpoint,
method,
serverPubkey,
serverUrl,
stringifiedBody: null,
doNotIncludeOurSogsHeaders: true, // the first capabilities needs to not have any authentification to pass on a blinding-required sogs,
headers: null,
throwErrors: false,
});
// not a batch call yet as we need to exclude headers for this call for now
if (!batchGlobalIsSuccess(result)) {
window?.log?.warn('Capabilities Request Got unknown status code; res:', result);
return null;
}
const parsedCapabilities = result?.body ? parseCapabilities(result.body) : [];
return parsedCapabilities;
};
/**
* @param body is the object containing a .capabilities field we should extract the list from.
* @returns the sorted list of capabilities contained in that response, or null
*/
export function parseCapabilities(body: any): null | Array<string> {
if (!body || isEmpty(body) || !isObject(body) || !isArray(body.capabilities)) {
return null;
}
return ((body.capabilities as Array<string>) || []).sort();
}
export type ParsedBase64Avatar = {
roomId: string;
base64: string;
};
export type ParsedMemberCount = {
roomId: string;
memberCount: number;
};
export function roomHasBlindEnabled(openGroup?: OpenGroupV2Room) {
return capabilitiesListHasBlindEnabled(openGroup?.capabilities);
}
export function capabilitiesListHasBlindEnabled(caps?: Array<string> | null) {
return Boolean(caps?.includes('blind'));
}
export function roomHasReactionsEnabled(openGroup?: OpenGroupV2Room) {
return Boolean(openGroup?.capabilities?.includes('reactions'));
}
export async function fetchCapabilitiesAndUpdateRelatedRoomsOfServerUrl(serverUrl: string) {
let relatedRooms = OpenGroupData.getV2OpenGroupRoomsByServerUrl(serverUrl);
if (!relatedRooms || relatedRooms.length === 0) {
return;
}
// we actually don't do that call using batch send for now to avoid having to deal with the headers in batch poll.
// these 2 requests below needs to not have sogs header at all and are unauthenticated
const capabilities = await capabilitiesFetchForServer(
serverUrl,
relatedRooms[0].serverPublicKey,
new AbortController().signal
);
if (!capabilities) {
return;
}
// just fetch updated data from the DB, just in case
relatedRooms = OpenGroupData.getV2OpenGroupRoomsByServerUrl(serverUrl);
if (!relatedRooms || relatedRooms.length === 0) {
return;
}
const newSortedCaps = capabilities.sort();
await Promise.all(
relatedRooms.map(async room => {
if (!isEqual(newSortedCaps, room.capabilities?.sort() || '')) {
room.capabilities = newSortedCaps;
await OpenGroupData.saveV2OpenGroupRoom(room);
}
})
);
return newSortedCaps;
}