This repository has been archived by the owner on Jun 28, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
82 lines (71 loc) · 2.75 KB
/
index.ts
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
type DefaultCommand<MesssageType = DefaultMessage> = {
run (this: Bot<MesssageType>, message: MesssageType, args: string[]): any
}
type DefaultMessage = {
content: string
}
interface Events<MessageType> {
output: [any, MessageType]
error: [any, MessageType]
message: MessageType
}
abstract class Bot<MesssageType = DefaultMessage, CommandObj extends DefaultCommand<MesssageType> = DefaultCommand<MesssageType>> {
protected events = new Map<string, Set<(arg: any) => void>>()
on<Key extends keyof Events<MesssageType>> (type: Key, handler: (arg: Events<MesssageType>[Key]) => void): void {
if (!this.events.has(type)) this.events.set(type, new Set)
this.events.get(type)?.add(handler)
}
emit<Key extends keyof Events<MesssageType>> (name: Key, event: Events<MesssageType>[Key]) {
if (!this.events.has(name)) this.events.set(name, new Set)
for (const func of this.events.get(name)!) func(event)
}
off (type: keyof Events<MesssageType>, callback: (arg: any) => void) {
this.events.get(type)?.delete(callback)
}
commands = new Map<string, CommandObj>()
aliases = new Map<string, string>()
abstract filter (msg: MesssageType): boolean
constructor(public prefix: string) {
this.on('message', async (message: MesssageType) => {
const content = (message as { content?: string }).content || message + ''
if (!this.filter(message)) return
const name = this.commandFromMessage(content)
if (!name) return
const command = this.getCommand(name)?.run || (() => { })
try {
const output = await command.call(
this,
message,
this.getArguments(content)
)
if (output) this.emit('output', [output, message])
} catch (error) {
this.emit('error', [error, message])
}
})
}
getCommandName (cmdname: string): string | undefined {
return this.commands.has(cmdname) ? cmdname : this.aliases.get(cmdname)
}
getCommand (name: string | undefined) {
if (!name) return undefined
if (this.commands.has(name) || this.aliases.has(name)) {
return this.commands.get(this.getCommandName(name!)!)
} else return
}
commandFromMessage (content: string): string | undefined {
return [...this.commands.keys(), ...this.aliases.keys()].find(
cmdname =>
content.startsWith(`${this.prefix}${cmdname} `) || // matches any command with a space after
content === `${this.prefix}${cmdname}` // matches any command without arguments
)
}
getArguments (content: string) {
const name = this.commandFromMessage(content)
if (!name) return []
return content
.substring(this.prefix.length + 1 + name.length) // only the part after the command
.split(' ') // split with spaces
}
}
export default Bot