feat(dispatcher): support regex commands
This commit is contained in:
parent
2682392d26
commit
fbb5d7005f
1 changed files with 27 additions and 15 deletions
|
@ -798,11 +798,14 @@ export namespace filters {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filter messages that match a given regular expression.
|
* Filter messages that call the given command(s)..
|
||||||
*
|
*
|
||||||
* When a command matches, the match array is stored in a
|
* When a command matches, the match array is stored in a
|
||||||
* type-safe extension field `.commmand` of the {@link Message} object.
|
* type-safe extension field `.commmand` of the {@link Message} object.
|
||||||
* First element is the command itself, then the arguments
|
* First element is the command itself, then the arguments.
|
||||||
|
*
|
||||||
|
* If the matched command was a RegExp, the first element is the full
|
||||||
|
* command, then the groups from the command regex, then the arguments.
|
||||||
*
|
*
|
||||||
* @param commands Command(s) the filter should look for (w/out prefix)
|
* @param commands Command(s) the filter should look for (w/out prefix)
|
||||||
* @param prefixes
|
* @param prefixes
|
||||||
|
@ -811,20 +814,27 @@ export namespace filters {
|
||||||
* @param caseSensitive
|
* @param caseSensitive
|
||||||
*/
|
*/
|
||||||
export const command = (
|
export const command = (
|
||||||
commands: MaybeArray<string>,
|
commands: MaybeArray<string | RegExp>,
|
||||||
prefixes: MaybeArray<string> | null = '/',
|
prefixes: MaybeArray<string> | null = '/',
|
||||||
caseSensitive = false
|
caseSensitive = false
|
||||||
): UpdateFilter<Message, { command: string[] }> => {
|
): UpdateFilter<Message, { command: string[] }> => {
|
||||||
if (typeof commands === 'string') commands = [commands]
|
if (!Array.isArray(commands)) commands = [commands]
|
||||||
commands = commands.map((i) => i.toLowerCase())
|
|
||||||
|
commands = commands.map((i) =>
|
||||||
|
typeof i === 'string' ? i.toLowerCase() : i
|
||||||
|
)
|
||||||
|
|
||||||
const argumentsRe = /(["'])(.*?)(?<!\\)\1|(\S+)/g
|
const argumentsRe = /(["'])(.*?)(?<!\\)\1|(\S+)/g
|
||||||
const unescapeRe = /\\(['"])/
|
const unescapeRe = /\\(['"])/
|
||||||
const commandsRe: Record<string, RegExp> = {}
|
const commandsRe: RegExp[] = []
|
||||||
commands.forEach((cmd) => {
|
commands.forEach((cmd) => {
|
||||||
commandsRe[cmd] = new RegExp(
|
if (typeof cmd !== 'string') cmd = cmd.source
|
||||||
`^${cmd}(?:\\s|$|@([a-zA-Z0-9_]+?bot)(?:\\s|$))`,
|
|
||||||
caseSensitive ? '' : 'i'
|
commandsRe.push(
|
||||||
|
new RegExp(
|
||||||
|
`^(${cmd})(?:\\s|$|@([a-zA-Z0-9_]+?bot)(?:\\s|$))`,
|
||||||
|
caseSensitive ? '' : 'i'
|
||||||
|
)
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -836,11 +846,12 @@ export namespace filters {
|
||||||
if (!msg.text.startsWith(pref)) continue
|
if (!msg.text.startsWith(pref)) continue
|
||||||
|
|
||||||
const withoutPrefix = msg.text.slice(pref.length)
|
const withoutPrefix = msg.text.slice(pref.length)
|
||||||
for (const cmd of commands) {
|
for (const regex of commandsRe) {
|
||||||
const m = withoutPrefix.match(commandsRe[cmd])
|
const m = withoutPrefix.match(regex)
|
||||||
if (!m) continue
|
if (!m) continue
|
||||||
|
|
||||||
if (m[1] && msg.client['_isBot']) {
|
const lastGroup = m[m.length - 1]
|
||||||
|
if (lastGroup && msg.client['_isBot']) {
|
||||||
// check bot username
|
// check bot username
|
||||||
if (!msg.client['_botUsername']) {
|
if (!msg.client['_botUsername']) {
|
||||||
// need to fetch it first
|
// need to fetch it first
|
||||||
|
@ -851,13 +862,14 @@ export namespace filters {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m[1] !== msg.client['_botUsername']) return false
|
if (lastGroup !== msg.client['_botUsername']) return false
|
||||||
}
|
}
|
||||||
|
|
||||||
const match = [cmd]
|
const match = m.slice(1, -1)
|
||||||
|
|
||||||
// we use .replace to iterate over global regex, not to replace the text
|
// we use .replace to iterate over global regex, not to replace the text
|
||||||
withoutPrefix
|
withoutPrefix
|
||||||
.slice(cmd.length)
|
.slice(m[0].length)
|
||||||
.replace(argumentsRe, ($0, $1, $2, $3) => {
|
.replace(argumentsRe, ($0, $1, $2, $3) => {
|
||||||
match.push(
|
match.push(
|
||||||
($2 || $3 || '').replace(unescapeRe, '$1')
|
($2 || $3 || '').replace(unescapeRe, '$1')
|
||||||
|
|
Loading…
Reference in a new issue