|
| 1 | +import React, { useEffect, useMemo, useRef } from 'react'; |
| 2 | +import { pluginLogger } from 'bigbluebutton-html-plugin-sdk'; |
| 3 | +import { |
| 4 | + CommandConfig, |
| 5 | + ChatCommandPluginProps, |
| 6 | + SetRoleMutation, |
| 7 | + MutationMap, |
| 8 | +} from './types'; |
| 9 | +import { SET_ROLE } from './mutations'; |
| 10 | + |
| 11 | +const COMMAND_PREFIX = '/'; |
| 12 | + |
| 13 | +const VIEWER_ROLE = () => window.meetingClientSettings.public.user.role_viewer; |
| 14 | +const MODERATOR_ROLE = () => window.meetingClientSettings.public.user.role_moderator; |
| 15 | + |
| 16 | +const DEFAULT_COMMANDS: CommandConfig = { |
| 17 | + demote: { |
| 18 | + name: 'demote', |
| 19 | + description: 'Demote all users to viewers except the sender', |
| 20 | + execute: ({ |
| 21 | + currentUser, |
| 22 | + users, |
| 23 | + senderId, |
| 24 | + mutation, |
| 25 | + }) => { |
| 26 | + if (!currentUser || currentUser.role !== MODERATOR_ROLE()) { |
| 27 | + pluginLogger.warn('Current user is not a moderator. Cannot execute demote command.'); |
| 28 | + return; |
| 29 | + } |
| 30 | + users |
| 31 | + .filter((user) => user.userId !== senderId && user.isModerator) |
| 32 | + .map((user) => mutation({ |
| 33 | + variables: { |
| 34 | + userId: user.userId, |
| 35 | + role: VIEWER_ROLE(), |
| 36 | + }, |
| 37 | + })); |
| 38 | + }, |
| 39 | + }, |
| 40 | +}; |
| 41 | + |
| 42 | +export function ChatCommandPlugin({ |
| 43 | + pluginApi, |
| 44 | + commands = DEFAULT_COMMANDS, |
| 45 | +}: ChatCommandPluginProps): React.ReactElement { |
| 46 | + const loadedChatMessagesResponse = pluginApi.useLoadedChatMessages(); |
| 47 | + const usersBasicInfoResponse = pluginApi.useUsersBasicInfo(); |
| 48 | + const currentUserResponse = pluginApi.useCurrentUser(); |
| 49 | + const [setRole] = pluginApi.useCustomMutation<SetRoleMutation>(SET_ROLE); |
| 50 | + const executedMessageIds = useRef<Set<string>>(new Set()); |
| 51 | + |
| 52 | + const mutationMap: MutationMap = useMemo(() => ({ |
| 53 | + [DEFAULT_COMMANDS.demote.name]: setRole, |
| 54 | + }), [setRole]); |
| 55 | + |
| 56 | + const currentUser = useMemo(() => { |
| 57 | + if (currentUserResponse.loading) return null; |
| 58 | + if (currentUserResponse.error || !currentUserResponse.data) { |
| 59 | + pluginLogger.error('Error loading current user', currentUserResponse.error); |
| 60 | + return null; |
| 61 | + } |
| 62 | + return currentUserResponse.data; |
| 63 | + }, [currentUserResponse]); |
| 64 | + |
| 65 | + const usersList = useMemo(() => { |
| 66 | + if (usersBasicInfoResponse.loading) return []; |
| 67 | + if (usersBasicInfoResponse.error || !usersBasicInfoResponse.data) { |
| 68 | + pluginLogger.error('Error loading user list', usersBasicInfoResponse.error); |
| 69 | + return []; |
| 70 | + } |
| 71 | + return usersBasicInfoResponse.data.user; |
| 72 | + }, [usersBasicInfoResponse]); |
| 73 | + |
| 74 | + const messages = useMemo(() => { |
| 75 | + if (loadedChatMessagesResponse.loading) return []; |
| 76 | + if (loadedChatMessagesResponse.error || !loadedChatMessagesResponse.data) { |
| 77 | + pluginLogger.error('Error loading chat messages', loadedChatMessagesResponse.error); |
| 78 | + return []; |
| 79 | + } |
| 80 | + return loadedChatMessagesResponse.data; |
| 81 | + }, [loadedChatMessagesResponse]); |
| 82 | + |
| 83 | + useEffect(() => { |
| 84 | + if (messages && usersList && currentUser) { |
| 85 | + messages.forEach(async (message) => { |
| 86 | + if (message.message.startsWith(COMMAND_PREFIX) |
| 87 | + && message.senderUserId === currentUser.userId |
| 88 | + && !executedMessageIds.current.has(message.messageId)) { |
| 89 | + const [cmd, ...args] = message.message.slice(1).split(' '); |
| 90 | + if (commands[cmd]) { |
| 91 | + pluginLogger.info(`Executing command: ${cmd} with args: ${args.join(', ')}`); |
| 92 | + commands[cmd].execute({ |
| 93 | + mutation: mutationMap[cmd], |
| 94 | + currentUser, |
| 95 | + users: usersList, |
| 96 | + senderId: message.senderUserId, |
| 97 | + args, |
| 98 | + }); |
| 99 | + executedMessageIds.current.add(message.messageId); |
| 100 | + } |
| 101 | + } |
| 102 | + }); |
| 103 | + } |
| 104 | + }, [messages, usersList, currentUser, commands]); |
| 105 | + |
| 106 | + return null; |
| 107 | +} |
| 108 | + |
| 109 | +export default ChatCommandPlugin; |
0 commit comments