cinny/src/app/hooks/useCommands.ts
Rein Fernhout 00d5553bcb
Some checks failed
Deploy to Netlify (dev) / Deploy to Netlify (push) Has been cancelled
add tableflip and unflip commands (#2075)
2024-12-13 10:02:25 +05:30

235 lines
7.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { MatrixClient, Room } from 'matrix-js-sdk';
import { useMemo } from 'react';
import { getDMRoomFor, isRoomAlias, isRoomId, isUserId } from '../utils/matrix';
import { hasDevices } from '../../util/matrixUtil';
import * as roomActions from '../../client/action/room';
import { useRoomNavigate } from './useRoomNavigate';
export const SHRUG = '¯\\_(ツ)_/¯';
export const TABLEFLIP = '(╯°□°)╯︵ ┻━┻';
export const UNFLIP = '┬─┬ノ( º_º)';
export function parseUsersAndReason(payload: string): {
users: string[];
reason?: string;
} {
let reason: string | undefined;
let ids: string = payload;
const reasonMatch = payload.match(/\s-r\s/);
if (reasonMatch) {
ids = payload.slice(0, reasonMatch.index);
reason = payload.slice((reasonMatch.index ?? 0) + reasonMatch[0].length);
if (reason.trim() === '') reason = undefined;
}
const rawIds = ids.split(' ');
const users = rawIds.filter((id) => isUserId(id));
return {
users,
reason,
};
}
export type CommandExe = (payload: string) => Promise<void>;
export enum Command {
Me = 'me',
Notice = 'notice',
Shrug = 'shrug',
StartDm = 'startdm',
Join = 'join',
Leave = 'leave',
Invite = 'invite',
DisInvite = 'disinvite',
Kick = 'kick',
Ban = 'ban',
UnBan = 'unban',
Ignore = 'ignore',
UnIgnore = 'unignore',
MyRoomNick = 'myroomnick',
MyRoomAvatar = 'myroomavatar',
ConvertToDm = 'converttodm',
ConvertToRoom = 'converttoroom',
TableFlip = 'tableflip',
UnFlip = 'unflip',
}
export type CommandContent = {
name: string;
description: string;
exe: CommandExe;
};
export type CommandRecord = Record<Command, CommandContent>;
export const useCommands = (mx: MatrixClient, room: Room): CommandRecord => {
const { navigateRoom } = useRoomNavigate();
const commands: CommandRecord = useMemo(
() => ({
[Command.Me]: {
name: Command.Me,
description: 'Send action message',
exe: async () => undefined,
},
[Command.Notice]: {
name: Command.Notice,
description: 'Send notice message',
exe: async () => undefined,
},
[Command.Shrug]: {
name: Command.Shrug,
description: 'Send ¯\\_(ツ)_/¯ as message',
exe: async () => undefined,
},
[Command.TableFlip]: {
name: Command.TableFlip,
description: `Send ${TABLEFLIP} as message`,
exe: async () => undefined,
},
[Command.UnFlip]: {
name: Command.UnFlip,
description: `Send ${UNFLIP} as message`,
exe: async () => undefined,
},
[Command.StartDm]: {
name: Command.StartDm,
description: 'Start direct message with user. Example: /startdm userId1',
exe: async (payload) => {
const rawIds = payload.split(' ');
const userIds = rawIds.filter((id) => isUserId(id) && id !== mx.getUserId());
if (userIds.length === 0) return;
if (userIds.length === 1) {
const dmRoomId = getDMRoomFor(mx, userIds[0])?.roomId;
if (dmRoomId) {
navigateRoom(dmRoomId);
return;
}
}
const devices = await Promise.all(userIds.map(uid => hasDevices(mx, uid)));
const isEncrypt = devices.every((hasDevice) => hasDevice);
const result = await roomActions.createDM(mx, userIds, isEncrypt);
navigateRoom(result.room_id);
},
},
[Command.Join]: {
name: Command.Join,
description: 'Join room with address. Example: /join address1 address2',
exe: async (payload) => {
const rawIds = payload.split(' ');
const roomIds = rawIds.filter(
(idOrAlias) => isRoomId(idOrAlias) || isRoomAlias(idOrAlias)
);
roomIds.map((id) => roomActions.join(mx, id));
},
},
[Command.Leave]: {
name: Command.Leave,
description: 'Leave current room.',
exe: async (payload) => {
if (payload.trim() === '') {
mx.leave(room.roomId);
return;
}
const rawIds = payload.split(' ');
const roomIds = rawIds.filter((id) => isRoomId(id));
roomIds.map((id) => mx.leave(id));
},
},
[Command.Invite]: {
name: Command.Invite,
description: 'Invite user to room. Example: /invite userId1 userId2 [-r reason]',
exe: async (payload) => {
const { users, reason } = parseUsersAndReason(payload);
users.map((id) => mx.invite(room.roomId, id, reason));
},
},
[Command.DisInvite]: {
name: Command.DisInvite,
description: 'Disinvite user to room. Example: /disinvite userId1 userId2 [-r reason]',
exe: async (payload) => {
const { users, reason } = parseUsersAndReason(payload);
users.map((id) => mx.kick(room.roomId, id, reason));
},
},
[Command.Kick]: {
name: Command.Kick,
description: 'Kick user from room. Example: /kick userId1 userId2 [-r reason]',
exe: async (payload) => {
const { users, reason } = parseUsersAndReason(payload);
users.map((id) => mx.kick(room.roomId, id, reason));
},
},
[Command.Ban]: {
name: Command.Ban,
description: 'Ban user from room. Example: /ban userId1 userId2 [-r reason]',
exe: async (payload) => {
const { users, reason } = parseUsersAndReason(payload);
users.map((id) => mx.ban(room.roomId, id, reason));
},
},
[Command.UnBan]: {
name: Command.UnBan,
description: 'Unban user from room. Example: /unban userId1 userId2',
exe: async (payload) => {
const rawIds = payload.split(' ');
const users = rawIds.filter((id) => isUserId(id));
users.map((id) => mx.unban(room.roomId, id));
},
},
[Command.Ignore]: {
name: Command.Ignore,
description: 'Ignore user. Example: /ignore userId1 userId2',
exe: async (payload) => {
const rawIds = payload.split(' ');
const userIds = rawIds.filter((id) => isUserId(id));
if (userIds.length > 0) roomActions.ignore(mx, userIds);
},
},
[Command.UnIgnore]: {
name: Command.UnIgnore,
description: 'Unignore user. Example: /unignore userId1 userId2',
exe: async (payload) => {
const rawIds = payload.split(' ');
const userIds = rawIds.filter((id) => isUserId(id));
if (userIds.length > 0) roomActions.unignore(mx, userIds);
},
},
[Command.MyRoomNick]: {
name: Command.MyRoomNick,
description: 'Change nick in current room.',
exe: async (payload) => {
const nick = payload.trim();
if (nick === '') return;
roomActions.setMyRoomNick(mx, room.roomId, nick);
},
},
[Command.MyRoomAvatar]: {
name: Command.MyRoomAvatar,
description: 'Change profile picture in current room. Example /myroomavatar mxc://xyzabc',
exe: async (payload) => {
if (payload.match(/^mxc:\/\/\S+$/)) {
roomActions.setMyRoomAvatar(mx, room.roomId, payload);
}
},
},
[Command.ConvertToDm]: {
name: Command.ConvertToDm,
description: 'Convert room to direct message',
exe: async () => {
roomActions.convertToDm(mx, room.roomId);
},
},
[Command.ConvertToRoom]: {
name: Command.ConvertToRoom,
description: 'Convert direct message to room',
exe: async () => {
roomActions.convertToRoom(mx, room.roomId);
},
},
}),
[mx, room, navigateRoom]
);
return commands;
};