-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathFormatChecker.ts
More file actions
117 lines (100 loc) · 3.62 KB
/
FormatChecker.ts
File metadata and controls
117 lines (100 loc) · 3.62 KB
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
import { Message, PartialMessage } from 'discord.js';
import { randomUUID } from 'crypto';
import { Logger } from 'pino';
import { Base, BaseConfig } from './Base';
import { Bot } from './Bot';
import { findTextChannelByName, isTextChannel } from './helpers';
type FunctionChecker = (message: Message, logger: Logger) => boolean;
export interface FormatCheckerConfig extends BaseConfig {
channelName: string;
checker: RegExp | FunctionChecker;
examples?: string[];
}
export class FormatChecker extends Base {
private readonly channelName: string;
private readonly checker: RegExp | FunctionChecker;
private readonly examples?: string[];
private bot: Bot | undefined;
public constructor(config: FormatCheckerConfig) {
super(config);
this.channelName = config.channelName;
if (
typeof config.checker === 'function' ||
config.checker instanceof RegExp
)
this.checker = config.checker;
else throw new Error(`invalid checker for ${this.name}`);
this.examples = config.examples;
this._messageHandler = this._messageHandler.bind(this);
this._messageUpdateHandler = this._messageUpdateHandler.bind(this);
}
async _messageHandler(message: Message): Promise<void> {
if (this.bot === undefined) return;
if (
!isTextChannel(message.channel) ||
message.channel.name !== this.channelName
)
return;
const logger = this.bot.logger.child({
id: randomUUID(),
type: 'FormatChecker',
checkerName: this.name,
});
if (this.checker instanceof RegExp) {
if (this.checker.test(message.cleanContent)) return;
} else if (this.checker(message, logger)) return;
const { cleanContent, author } = message;
logger.info(
{ userId: author.id, userTag: author.tag, cleanContent },
'Detected bad message format',
);
await message.delete();
const plural = this.examples !== undefined && this.examples.length > 1;
const pluralSuffix = plural ? 's' : '';
const warningContent = [
`Le message que vous avez posté dans ${message.channel} est incorrectement formaté, il a donc été supprimé.`,
'Pour rappel, voici le message que vous aviez envoyé :',
`\`\`\`\n${cleanContent}\n\`\`\``,
...(this.examples !== undefined
? [
`Voici ${
plural ? 'des' : 'un'
} example${pluralSuffix} de message${pluralSuffix} correctement formaté${pluralSuffix} :`,
...this.examples.map((example) => `\`\`\`\n${example}\`\`\``),
]
: []),
].join('\n');
try {
await author.send(`Bonjour,\n${warningContent}`);
} catch (err) {
if (err.code !== 50007 /* Cannot send messages to this user */) {
logger.error(
err,
'failed to send private message to user %s (id: %s)',
author.tag,
author.id,
);
}
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const channel = findTextChannelByName(message.guild!.channels, 'logs');
channel.send(`Bonjour ${author},\n${warningContent}`);
}
logger.debug('warning message sent');
}
async _messageUpdateHandler(
_oldMessage: Message | PartialMessage,
newMessage: Message | PartialMessage,
): Promise<void> {
return this._messageHandler(
newMessage.partial ? await newMessage.fetch() : newMessage,
);
}
public start(bot: Bot): void {
this.bot = bot;
this.bot.client.on('message', this._messageHandler);
this.bot.client.on('messageUpdate', this._messageUpdateHandler);
}
public stop(bot: Bot): void {
bot.client.off('message', this._messageHandler);
}
}