Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SlashCommand: tell the user when a parameter is missing #835

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions src/SlashCommands.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
interface SlashCommand {
export interface SlashCommand {
type: string;
description: string;
invocations: string[];
Expand Down Expand Up @@ -36,10 +36,13 @@ export const SlashCommands: SlashCommand[] = [
SlashCommand(SlashCommandType.Interact, 'Interact with or get something in a room by referencing the name in the description - experiment as you explore!', ['/interact', '/get'], false)
]

export function matchingSlashCommand (message: String): SlashCommand | undefined {
return SlashCommands.find((command) =>
command.invocations.find((invocation) =>
command.singleParameter ? message.startsWith(invocation) : message.startsWith(invocation + ' ')
)
)
export function matchingSlashCommand (cmd: string, arg: string | undefined): SlashCommand | 'SlashCommandArgumentExpected' | 'UnregisteredSlashCommand' {
const found = SlashCommands.find((command) => command.invocations.find((inv) => cmd === inv))
if (found === undefined) {
return 'UnregisteredSlashCommand'
}
if (!found.singleParameter && arg === undefined) {
return 'SlashCommandArgumentExpected'
}
return found
}
110 changes: 58 additions & 52 deletions src/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ import {
updateProfileColor
} from './networking'
import { Room } from './room'
import { matchingSlashCommand, SlashCommandType } from './SlashCommands'
import { matchingSlashCommand, SlashCommand, SlashCommandType } from './SlashCommands'
import * as Storage from './storage'
import { EntityState } from './types'

Expand Down Expand Up @@ -170,9 +170,9 @@ export default produce((draft: State, action: Action) => {

if (
original(draft).serverSettings.movementMessagesHideRoomIds !==
current(draft).serverSettings.movementMessagesHideRoomIds ||
current(draft).serverSettings.movementMessagesHideRoomIds ||
original(draft).serverSettings.movementMessagesHideThreshold !==
current(draft).serverSettings.movementMessagesHideThreshold
current(draft).serverSettings.movementMessagesHideThreshold
) {
draft.messages.ids = filteredMessageIds(draft)
}
Expand Down Expand Up @@ -496,10 +496,7 @@ export default produce((draft: State, action: Action) => {
if (action.type === ActionType.SendMessage) {
const messageId: string = uuidv4()
const trimmedMessage = action.value.trim()
const beginsWithSlash = /^\/.+?/.exec(trimmedMessage)
const matching = beginsWithSlash
? matchingSlashCommand(trimmedMessage)
: undefined
const slashCommandTokens = /^(\/\w+)(?:\s+(.+))?/.exec(trimmedMessage)

if (trimmedMessage.length > MESSAGE_MAX_LENGTH) {
addMessage(
Expand All @@ -508,59 +505,68 @@ export default produce((draft: State, action: Action) => {
'Your message is too long! Please try to keep it under ~600 characters!'
)
)
} else if (beginsWithSlash && matching === undefined) {
const commandStr = /^(\/.+?) (.+)/.exec(trimmedMessage)
addMessage(
draft,
createErrorMessage(
`Your command ${
commandStr ? commandStr[1] : action.value
} is not a registered slash command!`
)
)
} else if (beginsWithSlash && matching.type === SlashCommandType.Whisper) {
const commandStr = /^(\/.+?) (.+)/.exec(trimmedMessage)
const parsedUsernameMessage = /^(.+?) (.+)/.exec(commandStr[2])
} else if (slashCommandTokens !== null) {
// Handle server commands
const cmdToken = slashCommandTokens[1]
const cmdArg = slashCommandTokens.length > 1 ? slashCommandTokens[2] : undefined
const cmd = matchingSlashCommand(cmdToken, cmdArg)

if (!parsedUsernameMessage) {
if (cmd === 'UnregisteredSlashCommand') {
addMessage(
draft,
createErrorMessage(`Your whisper to ${commandStr[2]} had no message!`)
createErrorMessage(`Your command ${cmdToken} is not a registered slash command!`)
)
} else {
sendChatMessage(messageId, trimmedMessage)

const [_, username, message] = parsedUsernameMessage
const user = Object.values(draft.userMap).find(
(u) => u.username === username
} else if (cmd === 'SlashCommandArgumentExpected') {
addMessage(
draft,
createErrorMessage(`Your command ${cmdToken} expected an argument!`)
)
const userId = user && user.id
if (userId) {
const whisperMessage = createWhisperMessage(userId, message, true)
addMessage(draft, whisperMessage)
saveWhisper(draft, whisperMessage)
} else {
const sc = cmd as SlashCommand

if (sc.type === SlashCommandType.Whisper) {
const parsedUsernameMessage = /^(\w+)\s+(.+)/.exec(cmdArg)
if (!parsedUsernameMessage) {
addMessage(
draft,
createErrorMessage(`Your whisper to ${cmdArg} had no message!`)
)
} else {
sendChatMessage(messageId, trimmedMessage)

const [_, username, message] = parsedUsernameMessage
const user = Object.values(draft.userMap).find(
(u) => u.username === username
)
const userId = user && user.id
if (userId) {
const whisperMessage = createWhisperMessage(userId, message, true)
addMessage(draft, whisperMessage)
saveWhisper(draft, whisperMessage)
}
}
} else if (sc.type === SlashCommandType.Help) {
draft.activeModal = Modal.Help
addMessage(
draft,
createCommandMessage(
'You consult the help docs. (You can also find them in sidebar!)'
)
)
} else if (sc.type === SlashCommandType.Look) {
addMessage(
draft,
createCommandMessage(
`You attempt to examine ${cmdArg}. (You can also click on their username and select Profile!)`
)
)
sendChatMessage(messageId, trimmedMessage)
} else {
sendChatMessage(messageId, trimmedMessage)
}
}
} else if (beginsWithSlash && matching.type === SlashCommandType.Help) {
draft.activeModal = Modal.Help
addMessage(
draft,
createCommandMessage(
'You consult the help docs. (You can also find them in sidebar!)'
)
)
} else if (beginsWithSlash && matching.type === SlashCommandType.Look) {
const commandStr = /^(\/.+?) (.+)/.exec(trimmedMessage)
addMessage(
draft,
createCommandMessage(
`You attempt to examine ${commandStr[2]}. (You can also click on their username and select Profile!)`
)
)
sendChatMessage(messageId, trimmedMessage)
} else if (beginsWithSlash) {
sendChatMessage(messageId, trimmedMessage)
} else {
// Handle an ordinary chat message
sendChatMessage(messageId, action.value)
addMessage(
draft,
Expand Down