2021-07-28 13:15:52 +00:00
|
|
|
import initMatrix from '../client/initMatrix';
|
|
|
|
|
2022-02-16 14:22:51 +00:00
|
|
|
import HashIC from '../../public/res/ic/outlined/hash.svg';
|
|
|
|
import HashGlobeIC from '../../public/res/ic/outlined/hash-globe.svg';
|
|
|
|
import HashLockIC from '../../public/res/ic/outlined/hash-lock.svg';
|
|
|
|
import SpaceIC from '../../public/res/ic/outlined/space.svg';
|
|
|
|
import SpaceGlobeIC from '../../public/res/ic/outlined/space-globe.svg';
|
|
|
|
import SpaceLockIC from '../../public/res/ic/outlined/space-lock.svg';
|
|
|
|
|
2021-07-28 13:15:52 +00:00
|
|
|
const WELL_KNOWN_URI = '/.well-known/matrix/client';
|
|
|
|
|
2022-02-23 14:00:48 +00:00
|
|
|
export async function getBaseUrl(servername) {
|
2021-11-06 09:45:35 +00:00
|
|
|
let protocol = 'https://';
|
|
|
|
if (servername.match(/^https?:\/\//) !== null) protocol = '';
|
|
|
|
const serverDiscoveryUrl = `${protocol}${servername}${WELL_KNOWN_URI}`;
|
2021-07-28 13:15:52 +00:00
|
|
|
try {
|
2021-11-06 09:45:35 +00:00
|
|
|
const result = await (await fetch(serverDiscoveryUrl, { method: 'GET' })).json();
|
2021-07-28 13:15:52 +00:00
|
|
|
|
2021-11-06 09:45:35 +00:00
|
|
|
const baseUrl = result?.['m.homeserver']?.base_url;
|
|
|
|
if (baseUrl === undefined) throw new Error();
|
|
|
|
return baseUrl;
|
2021-07-28 13:15:52 +00:00
|
|
|
} catch (e) {
|
2022-07-09 08:28:57 +00:00
|
|
|
return `${protocol}${servername}`;
|
2021-07-28 13:15:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-23 14:00:48 +00:00
|
|
|
export function getUsername(userId) {
|
2021-07-28 13:15:52 +00:00
|
|
|
const mx = initMatrix.matrixClient;
|
|
|
|
const user = mx.getUser(userId);
|
|
|
|
if (user === null) return userId;
|
|
|
|
let username = user.displayName;
|
|
|
|
if (typeof username === 'undefined') {
|
|
|
|
username = userId;
|
|
|
|
}
|
|
|
|
return username;
|
|
|
|
}
|
|
|
|
|
2022-02-23 14:00:48 +00:00
|
|
|
export function getUsernameOfRoomMember(roomMember) {
|
2021-08-25 08:36:13 +00:00
|
|
|
return roomMember.name || roomMember.userId;
|
|
|
|
}
|
|
|
|
|
2022-02-23 14:00:48 +00:00
|
|
|
export async function isRoomAliasAvailable(alias) {
|
2021-07-28 13:15:52 +00:00
|
|
|
try {
|
|
|
|
const result = await initMatrix.matrixClient.resolveRoomAlias(alias);
|
2022-01-01 06:13:35 +00:00
|
|
|
if (result.room_id) return false;
|
|
|
|
return false;
|
2021-07-28 13:15:52 +00:00
|
|
|
} catch (e) {
|
|
|
|
if (e.errcode === 'M_NOT_FOUND') return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-23 14:00:48 +00:00
|
|
|
export function getPowerLabel(powerLevel) {
|
2021-10-18 15:25:52 +00:00
|
|
|
if (powerLevel > 9000) return 'Goku';
|
|
|
|
if (powerLevel > 100) return 'Founder';
|
|
|
|
if (powerLevel === 100) return 'Admin';
|
|
|
|
if (powerLevel >= 50) return 'Mod';
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2022-02-23 14:00:48 +00:00
|
|
|
export function parseReply(rawBody) {
|
2021-12-03 13:02:10 +00:00
|
|
|
if (rawBody?.indexOf('>') !== 0) return null;
|
|
|
|
let body = rawBody.slice(rawBody.indexOf('<') + 1);
|
|
|
|
const user = body.slice(0, body.indexOf('>'));
|
|
|
|
|
|
|
|
body = body.slice(body.indexOf('>') + 2);
|
|
|
|
const replyBody = body.slice(0, body.indexOf('\n\n'));
|
|
|
|
body = body.slice(body.indexOf('\n\n') + 2);
|
|
|
|
|
|
|
|
if (user === '') return null;
|
|
|
|
|
|
|
|
const isUserId = user.match(/^@.+:.+/);
|
|
|
|
|
|
|
|
return {
|
|
|
|
userId: isUserId ? user : null,
|
|
|
|
displayName: isUserId ? null : user,
|
|
|
|
replyBody,
|
|
|
|
body,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-02-23 14:00:48 +00:00
|
|
|
export function hasDMWith(userId) {
|
2022-02-05 13:55:59 +00:00
|
|
|
const mx = initMatrix.matrixClient;
|
|
|
|
const directIds = [...initMatrix.roomList.directs];
|
|
|
|
|
|
|
|
return directIds.find((roomId) => {
|
|
|
|
const dRoom = mx.getRoom(roomId);
|
|
|
|
const roomMembers = dRoom.getMembers();
|
|
|
|
if (roomMembers.length <= 2 && dRoom.getMember(userId)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2022-02-23 14:00:48 +00:00
|
|
|
export function joinRuleToIconSrc(joinRule, isSpace) {
|
2022-02-16 14:22:51 +00:00
|
|
|
return ({
|
|
|
|
restricted: () => (isSpace ? SpaceIC : HashIC),
|
2022-03-06 12:18:31 +00:00
|
|
|
knock: () => (isSpace ? SpaceLockIC : HashLockIC),
|
2022-02-16 14:22:51 +00:00
|
|
|
invite: () => (isSpace ? SpaceLockIC : HashLockIC),
|
|
|
|
public: () => (isSpace ? SpaceGlobeIC : HashGlobeIC),
|
|
|
|
}[joinRule]?.() || null);
|
|
|
|
}
|
|
|
|
|
2022-02-23 14:00:48 +00:00
|
|
|
// NOTE: it gives userId with minimum power level 50;
|
|
|
|
function getHighestPowerUserId(room) {
|
|
|
|
const userIdToPower = room.currentState.getStateEvents('m.room.power_levels', '')?.getContent().users;
|
|
|
|
let powerUserId = null;
|
|
|
|
if (!userIdToPower) return powerUserId;
|
|
|
|
|
|
|
|
Object.keys(userIdToPower).forEach((userId) => {
|
|
|
|
if (userIdToPower[userId] < 50) return;
|
|
|
|
if (powerUserId === null) {
|
|
|
|
powerUserId = userId;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (userIdToPower[userId] > userIdToPower[powerUserId]) {
|
|
|
|
powerUserId = userId;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
return powerUserId;
|
|
|
|
}
|
|
|
|
|
|
|
|
export function getIdServer(userId) {
|
|
|
|
const idParts = userId.split(':');
|
|
|
|
return idParts[1];
|
|
|
|
}
|
|
|
|
|
|
|
|
export function getServerToPopulation(room) {
|
|
|
|
const members = room.getMembers();
|
|
|
|
const serverToPop = {};
|
|
|
|
|
|
|
|
members?.forEach((member) => {
|
|
|
|
const { userId } = member;
|
|
|
|
const server = getIdServer(userId);
|
|
|
|
const serverPop = serverToPop[server];
|
|
|
|
if (serverPop === undefined) {
|
|
|
|
serverToPop[server] = 1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
serverToPop[server] = serverPop + 1;
|
|
|
|
});
|
|
|
|
|
|
|
|
return serverToPop;
|
|
|
|
}
|
|
|
|
|
|
|
|
export function genRoomVia(room) {
|
|
|
|
const via = [];
|
|
|
|
const userId = getHighestPowerUserId(room);
|
|
|
|
if (userId) {
|
|
|
|
const server = getIdServer(userId);
|
|
|
|
if (server) via.push(server);
|
|
|
|
}
|
|
|
|
const serverToPop = getServerToPopulation(room);
|
|
|
|
const sortedServers = Object.keys(serverToPop).sort(
|
|
|
|
(svrA, svrB) => serverToPop[svrB] - serverToPop[svrA],
|
|
|
|
);
|
|
|
|
const mostPop3 = sortedServers.slice(0, 3);
|
|
|
|
if (via.length === 0) return mostPop3;
|
|
|
|
if (mostPop3.includes(via[0])) {
|
|
|
|
mostPop3.splice(mostPop3.indexOf(via[0]), 1);
|
|
|
|
}
|
|
|
|
return via.concat(mostPop3.slice(0, 2));
|
|
|
|
}
|
2022-04-24 10:12:24 +00:00
|
|
|
|
|
|
|
export function isCrossVerified(deviceId) {
|
|
|
|
try {
|
|
|
|
const mx = initMatrix.matrixClient;
|
|
|
|
const crossSignInfo = mx.getStoredCrossSigningForUser(mx.getUserId());
|
|
|
|
const deviceInfo = mx.getStoredDevice(mx.getUserId(), deviceId);
|
|
|
|
const deviceTrust = crossSignInfo.checkDeviceTrust(crossSignInfo, deviceInfo, false, true);
|
|
|
|
return deviceTrust.isCrossSigningVerified();
|
|
|
|
} catch {
|
2022-04-24 16:29:50 +00:00
|
|
|
// device does not support encryption
|
|
|
|
return null;
|
2022-04-24 10:12:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function hasCrossSigningAccountData() {
|
|
|
|
const mx = initMatrix.matrixClient;
|
|
|
|
const masterKeyData = mx.getAccountData('m.cross_signing.master');
|
|
|
|
return !!masterKeyData;
|
|
|
|
}
|
|
|
|
|
|
|
|
export function getDefaultSSKey() {
|
|
|
|
const mx = initMatrix.matrixClient;
|
|
|
|
try {
|
|
|
|
return mx.getAccountData('m.secret_storage.default_key').getContent().key;
|
|
|
|
} catch {
|
|
|
|
return undefined;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function getSSKeyInfo(key) {
|
|
|
|
const mx = initMatrix.matrixClient;
|
|
|
|
try {
|
|
|
|
return mx.getAccountData(`m.secret_storage.key.${key}`).getContent();
|
|
|
|
} catch {
|
|
|
|
return undefined;
|
|
|
|
}
|
|
|
|
}
|
2022-07-08 14:54:35 +00:00
|
|
|
|
|
|
|
export async function hasDevices(userId) {
|
|
|
|
const mx = initMatrix.matrixClient;
|
|
|
|
try {
|
|
|
|
const usersDeviceMap = await mx.downloadKeys([userId, mx.getUserId()]);
|
2022-07-09 08:28:57 +00:00
|
|
|
return Object.values(usersDeviceMap)
|
|
|
|
.every((userDevices) => (Object.keys(userDevices).length > 0));
|
2022-07-08 14:54:35 +00:00
|
|
|
} catch (e) {
|
|
|
|
console.error("Error determining if it's possible to encrypt to all users: ", e);
|
|
|
|
return false;
|
|
|
|
}
|
2022-07-09 08:28:57 +00:00
|
|
|
}
|