cinny/src/app/organisms/room/commands.jsx
2022-09-11 12:18:32 +05:30

220 lines
6.6 KiB
JavaScript

import React from 'react';
import './commands.scss';
import initMatrix from '../../../client/initMatrix';
import * as roomActions from '../../../client/action/room';
import { hasDMWith, hasDevices } from '../../../util/matrixUtil';
import { selectRoom, openReusableDialog } from '../../../client/action/navigation';
import Text from '../../atoms/text/Text';
import SettingTile from '../../molecules/setting-tile/SettingTile';
const MXID_REG = /^@\S+:\S+$/;
const ROOM_ID_ALIAS_REG = /^(#|!)\S+:\S+$/;
const ROOM_ID_REG = /^!\S+:\S+$/;
const MXC_REG = /^mxc:\/\/\S+$/;
export function processMxidAndReason(data) {
let reason;
let idData = data;
const reasonMatch = data.match(/\s-r\s/);
if (reasonMatch) {
idData = data.slice(0, reasonMatch.index);
reason = data.slice(reasonMatch.index + reasonMatch[0].length);
if (reason.trim() === '') reason = undefined;
}
const rawIds = idData.split(' ');
const userIds = rawIds.filter((id) => id.match(MXID_REG));
return {
userIds,
reason,
};
}
const commands = {
me: {
name: 'me',
description: 'Display action',
exe: (roomId, data, onSuccess) => {
const body = data.trim();
if (body === '') return;
onSuccess(body, { msgType: 'm.emote' });
},
},
shrug: {
name: 'shrug',
description: 'Send ¯\\_(ツ)_/¯ as message',
exe: (roomId, data, onSuccess) => onSuccess(
`¯\\_(ツ)_/¯${data.trim() !== '' ? ` ${data}` : ''}`,
{ msgType: 'm.text' },
),
},
plain: {
name: 'plain',
description: 'Send plain text message',
exe: (roomId, data, onSuccess) => {
const body = data.trim();
if (body === '') return;
onSuccess(body, { msgType: 'm.text', autoMarkdown: false });
},
},
help: {
name: 'help',
description: 'View all commands',
// eslint-disable-next-line no-use-before-define
exe: () => openHelpDialog(),
},
startdm: {
name: 'startdm',
description: 'Start direct message with user. Example: /startdm userId1',
exe: async (roomId, data) => {
const mx = initMatrix.matrixClient;
const rawIds = data.split(' ');
const userIds = rawIds.filter((id) => id.match(MXID_REG) && id !== mx.getUserId());
if (userIds.length === 0) return;
if (userIds.length === 1) {
const dmRoomId = hasDMWith(userIds[0]);
if (dmRoomId) {
selectRoom(dmRoomId);
return;
}
}
const devices = await Promise.all(userIds.map(hasDevices));
const isEncrypt = devices.every((hasDevice) => hasDevice);
const result = await roomActions.createDM(userIds, isEncrypt);
selectRoom(result.room_id);
},
},
join: {
name: 'join',
description: 'Join room with address. Example: /join address1 address2',
exe: (roomId, data) => {
const rawIds = data.split(' ');
const roomIds = rawIds.filter((id) => id.match(ROOM_ID_ALIAS_REG));
roomIds.map((id) => roomActions.join(id));
},
},
leave: {
name: 'leave',
description: 'Leave current room.',
exe: (roomId, data) => {
if (data.trim() === '') {
roomActions.leave(roomId);
return;
}
const rawIds = data.split(' ');
const roomIds = rawIds.filter((id) => id.match(ROOM_ID_REG));
roomIds.map((id) => roomActions.leave(id));
},
},
invite: {
name: 'invite',
description: 'Invite user to room. Example: /invite userId1 userId2 [-r reason]',
exe: (roomId, data) => {
const { userIds, reason } = processMxidAndReason(data);
userIds.map((id) => roomActions.invite(roomId, id, reason));
},
},
disinvite: {
name: 'disinvite',
description: 'Disinvite user to room. Example: /disinvite userId1 userId2 [-r reason]',
exe: (roomId, data) => {
const { userIds, reason } = processMxidAndReason(data);
userIds.map((id) => roomActions.kick(roomId, id, reason));
},
},
kick: {
name: 'kick',
description: 'Kick user from room. Example: /kick userId1 userId2 [-r reason]',
exe: (roomId, data) => {
const { userIds, reason } = processMxidAndReason(data);
userIds.map((id) => roomActions.kick(roomId, id, reason));
},
},
ban: {
name: 'ban',
description: 'Ban user from room. Example: /ban userId1 userId2 [-r reason]',
exe: (roomId, data) => {
const { userIds, reason } = processMxidAndReason(data);
userIds.map((id) => roomActions.ban(roomId, id, reason));
},
},
unban: {
name: 'unban',
description: 'Unban user from room. Example: /unban userId1 userId2',
exe: (roomId, data) => {
const rawIds = data.split(' ');
const userIds = rawIds.filter((id) => id.match(MXID_REG));
userIds.map((id) => roomActions.unban(roomId, id));
},
},
ignore: {
name: 'ignore',
description: 'Ignore user. Example: /ignore userId1 userId2',
exe: (roomId, data) => {
const rawIds = data.split(' ');
const userIds = rawIds.filter((id) => id.match(MXID_REG));
if (userIds.length > 0) roomActions.ignore(userIds);
},
},
unignore: {
name: 'unignore',
description: 'Unignore user. Example: /unignore userId1 userId2',
exe: (roomId, data) => {
const rawIds = data.split(' ');
const userIds = rawIds.filter((id) => id.match(MXID_REG));
if (userIds.length > 0) roomActions.unignore(userIds);
},
},
myroomnick: {
name: 'myroomnick',
description: 'Change nick in current room.',
exe: (roomId, data) => {
const nick = data.trim();
if (nick === '') return;
roomActions.setMyRoomNick(roomId, nick);
},
},
myroomavatar: {
name: 'myroomavatar',
description: 'Change profile picture in current room. Example /myroomavatar mxc://xyzabc',
exe: (roomId, data) => {
if (data.match(MXC_REG)) {
roomActions.setMyRoomAvatar(roomId, data);
}
},
},
converttodm: {
name: 'converttodm',
description: 'Convert room to direct message',
exe: (roomId) => {
roomActions.convertToDm(roomId);
},
},
converttoroom: {
name: 'converttoroom',
description: 'Convert direct message to room',
exe: (roomId) => {
roomActions.convertToRoom(roomId);
},
},
};
function openHelpDialog() {
openReusableDialog(
<Text variant="s1" weight="medium">Commands</Text>,
() => (
<div className="commands-dialog">
{Object.keys(commands).map((cmdName) => (
<SettingTile
key={cmdName}
title={cmdName}
content={<Text variant="b3">{commands[cmdName].description}</Text>}
/>
))}
</div>
),
);
}
export default commands;