-
Notifications
You must be signed in to change notification settings - Fork 2
/
index.js
129 lines (102 loc) · 3.63 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
const S = require('./string');
const PREFIX = '`';
const STRICT = true;
const map = new WeakMap();
class Slash {
constructor(dispatch) {
this.dispatch = dispatch;
const base = dispatch.base || dispatch;
if (!map.has(base)) {
map.set(base, {});
const runCommand = (raw, target) => {
// construct `args` array/object
const args = S.decodeHTMLEntities(S.stripTags(raw)).split(/\s+/);
Object.assign(args, { raw, target });
// run command handler
const cmd = args[0].slice(this.prefixRaw.length).toLowerCase();
const cb = map.get(base)[cmd];
if (typeof cb === 'function') {
cb(args);
return false;
}
// no command handler - check if strict mode
if (STRICT) {
console.error('[slash] Unrecognized command:', cmd);
return false;
}
};
// check if the message begins with the command and, if so, run it
// otherwise check if it begins with an escaped command
const parseMessage = (event) => {
const { message } = event;
const pos = (message.startsWith('<FONT>') ? 6 : 0);
if (message.startsWith(this.prefix, pos)) {
return runCommand(message, event.target || event.channel);
}
// if prefix is escaped by any number of backslashes '\',
// strip one off and send the rest as-is
const regexp = new RegExp('^\\\\+' + S.escapeRegExp(this.prefix));
if (regexp.test(message.slice(pos))) {
event.message = message.slice(0, pos) + message.slice(pos + 1);
return true;
}
};
dispatch.hook('C_CHAT', 1, {order: 10}, (event) => {
return parseMessage(event);
});
dispatch.hook('C_WHISPER', 1, {order: 10}, (event) => {
// if prefixed command, use that first
const res = parseMessage(event);
if (res === false) {
// we only check false because parseMessage() may return true if it
// was an escaped command; in that case, we should continue as normal
// since the whisper target might be in slash command format
// however, if it returns false, it successfully processed the command
// so we don't need to do anything more
return false;
}
// otherwise, use whisper target
const { target, message } = event;
// target can begin with either '/' or the raw prefix
// (TERA does not HTML encode whisper target)
let pos = -1;
if (target.startsWith('/')) {
pos = 1;
} else if (target.startsWith(this.prefixRaw)) {
pos = this.prefixRaw.length;
}
if (pos !== -1) {
// normalize the command string so that it looks like prefix form
const cmd = this.prefix + target.slice(pos);
const normalizedMessage = message.startsWith('<FONT>')
? `<FONT>${cmd} ${message.slice(6)}`
: `${cmd} ${message}`;
return runCommand(normalizedMessage, 7); // set to whisper channel
}
});
}
}
on(command, cb) {
const cmd = command.toLowerCase()
const cmds = map.get(this.dispatch.base);
if (cmds[cmd]) {
console.warn('[slash] Overriding handler for command:', cmd);
}
cmds[cmd] = cb;
}
print(message, formatted) {
message += ''; // cast to string
if (!formatted) message = S.escapeHTML(message);
this.dispatch.toClient('S_CHAT', 1, { message, channel: 206 });
}
get prefix() {
return S.escapeHTML(PREFIX);
}
get prefixRaw() {
return PREFIX;
}
get strict() {
return STRICT;
}
}
module.exports = Slash;