Skip to content

Commit 31880bd

Browse files
authored
Merge pull request #138 from vyneer/feat/phrases
DES-167: update banned phrases handling
2 parents b816bf7 + d9f0371 commit 31880bd

File tree

10 files changed

+158
-48
lines changed

10 files changed

+158
-48
lines changed

index.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ services
4545
.then(() => {
4646
logger.info(`Configuring for ${chatToConnectTo} chat`);
4747
const commandRouter = new CommandRouter(services);
48-
const messageRouter = new MessageRouter({}, services);
48+
const messageRouter = new MessageRouter({ chatConnectedTo: chatToConnectTo }, services);
4949
let bot = null;
5050

5151
if (chatToConnectTo === 'twitch') {
@@ -70,6 +70,7 @@ services
7070
services.scheduledCommands,
7171
services.fakeScheduler,
7272
services.messageRelay,
73+
services.bannedPhrases,
7374
);
7475
chatServiceRouter.create();
7576
})

lib/chat-utils/parse-commands-from-chat.js

+10
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,14 @@ function parseCommand(message) {
6060
return { commandString: commandString.toLowerCase(), input };
6161
}
6262

63+
function formatAddPhrase(phrase) {
64+
return `ADDPHRASE ${JSON.stringify({ data: phrase })}`;
65+
}
66+
67+
function formatRemovePhrase(phrase) {
68+
return `REMOVEPHRASE ${JSON.stringify({ data: phrase })}`;
69+
}
70+
6371
module.exports = {
6472
parseMessage,
6573
parseCommand,
@@ -71,4 +79,6 @@ module.exports = {
7179
formatPoll,
7280
parseWhisper,
7381
formatWhisper,
82+
formatAddPhrase,
83+
formatRemovePhrase,
7484
};

lib/commands/implementations/banphrase.js

+25-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ const Command = require('../command-interface');
33
const CommandOutput = require('../command-output');
44
const parseDurationToSeconds = require('../../chat-utils/duration-parser');
55

6-
function banphrase(defaultPunishmentDuration, punishmentType) {
6+
function banPhraseTwitch(defaultPunishmentDuration, punishmentType) {
77
return (input, services) => {
88
const matched = /(\d+[HMDSWwhmds])?\s?(.*)/.exec(input);
99
const duration = _.get(matched, 1, '');
@@ -50,7 +50,29 @@ function banphrase(defaultPunishmentDuration, punishmentType) {
5050
};
5151
}
5252

53+
function banPhraseDGG() {
54+
return (input, services) => {
55+
const matched = /(\d+[HMDSWwhmds])?\s?(.*)/.exec(input);
56+
const bannedPhrase = _.get(matched, 2, '').toLowerCase();
57+
services.bannedPhrases.addBannedPhrase(bannedPhrase);
58+
return new CommandOutput(null, 'Phrase banned!');
59+
};
60+
}
61+
5362
module.exports = {
54-
addban: new Command(banphrase(1800, 'ban'), true, true, /(\d+[HMDSWwhmds])?\s?(.*)/, false),
55-
addmute: new Command(banphrase(600, 'mute'), true, true, /(\d+[HMDSWwhmds])?\s?(.*)/, false),
63+
addbanTwitch: new Command(
64+
banPhraseTwitch(1800, 'ban'),
65+
true,
66+
true,
67+
/(\d+[HMDSWwhmds])?\s?(.*)/,
68+
false,
69+
),
70+
addmuteTwitch: new Command(
71+
banPhraseTwitch(600, 'mute'),
72+
true,
73+
true,
74+
/(\d+[HMDSWwhmds])?\s?(.*)/,
75+
false,
76+
),
77+
addbanDGG: new Command(banPhraseDGG(), false, true, /(\d+[HMDSWwhmds])?\s?(.*)/, false),
5678
};

lib/commands/implementations/unbanphrase.js

+27-14
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,32 @@ const _ = require('lodash');
22
const Command = require('../command-interface');
33
const CommandOutput = require('../command-output');
44

5-
function banphrase(input, services) {
6-
const matched = /(.*)/.exec(input);
7-
const phraseToUnban = _.get(matched, 1, '').toLowerCase();
8-
if (services.spamDetection.hasBannedPhrase(phraseToUnban) === false) {
9-
return Promise.resolve(new CommandOutput(null, 'Phrase is not registered! Did nothing.'));
10-
}
11-
return services.sql
12-
.deleteBannedPhrase(phraseToUnban)
13-
.then(() => {
14-
services.spamDetection.removeBannedPhrase(phraseToUnban);
15-
return new CommandOutput(null, 'Phrase unbanned! AngelThump');
16-
})
17-
.catch((err) => new CommandOutput(err, 'Oops. Something did not work. Check the logs.'));
5+
function unbanPhraseTwitch() {
6+
return (input, services) => {
7+
const matched = /(.*)/.exec(input);
8+
const phraseToUnban = _.get(matched, 1, '').toLowerCase();
9+
if (services.spamDetection.hasBannedPhrase(phraseToUnban) === false) {
10+
return Promise.resolve(new CommandOutput(null, 'Phrase is not registered! Did nothing.'));
11+
}
12+
return services.sql
13+
.deleteBannedPhrase(phraseToUnban)
14+
.then(() => {
15+
services.spamDetection.removeBannedPhrase(phraseToUnban);
16+
return new CommandOutput(null, 'Phrase unbanned! AngelThump');
17+
})
18+
.catch((err) => new CommandOutput(err, 'Oops. Something did not work. Check the logs.'));
19+
};
1820
}
1921

20-
module.exports = new Command(banphrase, true, true, /(.*)/, false);
22+
function unbanPhraseDGG() {
23+
return (input, services) => {
24+
const bannedPhrase = input;
25+
services.bannedPhrases.removeBannedPhrase(bannedPhrase);
26+
return new CommandOutput(null, 'Phrase unbanned! AngelThump');
27+
};
28+
}
29+
30+
module.exports = {
31+
unbanphraseTwitch: new Command(unbanPhraseTwitch(), true, true, /(.*)/, false),
32+
unbanphraseDGG: new Command(unbanPhraseDGG(), false, true),
33+
};

lib/configuration/configure-commands.js

+22-5
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ const song = require('../commands/implementations/song');
1616
const earlierSong = require('../commands/implementations/earliersong');
1717
const youtube = require('../commands/implementations/youtube');
1818
const schedule = require('../commands/implementations/schedule');
19-
const { addban, addmute } = require('../commands/implementations/banphrase');
20-
const unbanphrase = require('../commands/implementations/unbanphrase');
19+
const { addbanDGG, addbanTwitch, addmuteTwitch } = require('../commands/implementations/banphrase');
20+
const { unbanphraseDGG, unbanphraseTwitch } = require('../commands/implementations/unbanphrase');
2121
const live = require('../commands/implementations/live');
2222
const restart = require('../commands/implementations/restart');
2323
const love = require('../commands/implementations/love');
@@ -66,9 +66,6 @@ function registerCommandsFromFiles(commandRegistry, chatConnectedTo, config) {
6666
}
6767
commandRegistry.registerCommand('!youtube', youtube, ['!video', '!lastvideo', '!yt']);
6868
commandRegistry.registerCommand('!schedule', schedule, ['!sch']);
69-
commandRegistry.registerCommand('!addban', addban);
70-
commandRegistry.registerCommand('!addmute', addmute);
71-
commandRegistry.registerCommand('!deleteban', unbanphrase, ['!deletemute', '!dmute', '!dban']);
7269
commandRegistry.registerCommand('!live', live, ['!uptime']);
7370
commandRegistry.registerCommand('!restart', restart);
7471
commandRegistry.registerCommand('!love', love);
@@ -85,6 +82,14 @@ function registerCommandsFromFiles(commandRegistry, chatConnectedTo, config) {
8582
commandRegistry.registerCommand('!breakingnews', breakingNews, ['!breaking', '!bn']);
8683

8784
if (chatConnectedTo === 'dgg') {
85+
commandRegistry.registerCommand('!addban', addbanDGG, ['!addmute']);
86+
commandRegistry.registerCommand('!deleteban', unbanphraseDGG, [
87+
'!deletemute',
88+
'!removeban',
89+
'!removemute',
90+
'!dmute',
91+
'!dban',
92+
]);
8893
commandRegistry.registerCommand('!voteban', voteBan);
8994
commandRegistry.registerCommand('!voteipban', voteIpban);
9095
commandRegistry.registerCommand('!svoteban', svoteBan);
@@ -105,6 +110,18 @@ function registerCommandsFromFiles(commandRegistry, chatConnectedTo, config) {
105110
]);
106111
commandRegistry.registerCommand('!gulag', gulag);
107112
}
113+
114+
if (chatConnectedTo === 'twitch') {
115+
commandRegistry.registerCommand('!addban', addbanTwitch);
116+
commandRegistry.registerCommand('!addmute', addmuteTwitch);
117+
commandRegistry.registerCommand('!deleteban', unbanphraseTwitch, [
118+
'!deletemute',
119+
'!removeban',
120+
'!removemute',
121+
'!dmute',
122+
'!dban',
123+
]);
124+
}
108125
}
109126

110127
async function setupCommandsAndCachesFromDb(

lib/message-routing/chat-service-router.js

+15
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ class ChatServiceRouter {
1111
messageSchedulerStream,
1212
fakeScheduler,
1313
messageRelay,
14+
bannedPhrases,
1415
) {
1516
this.messageRouter = messageRouter;
1617
this.commandRouter = commandRouter;
@@ -22,6 +23,7 @@ class ChatServiceRouter {
2223
this.fakeScheduler = fakeScheduler;
2324
// TODO just refactor other things to use the message relay
2425
this.messageRelay = messageRelay;
26+
this.bannedPhrases = bannedPhrases;
2527
}
2628

2729
create() {
@@ -160,6 +162,19 @@ class ChatServiceRouter {
160162
this.bot.sendMessage(punishmentObject.reason);
161163
}
162164
});
165+
166+
this.bannedPhrases.on('data', (obj) => {
167+
switch (obj.action) {
168+
case 'add':
169+
this.bot.sendAddPhrase(obj.phrase);
170+
break;
171+
case 'remove':
172+
this.bot.sendRemovePhrase(obj.phrase);
173+
break;
174+
default:
175+
break;
176+
}
177+
})
163178
}
164179
}
165180

lib/message-routing/message-router.js

+28-25
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class MessageRouter {
2020
this.spamDetection = services.spamDetection;
2121
this.roleCache = services.roleCache;
2222
this.messageRelay = services.messageRelay;
23+
this.chatConnectedTo = config.chatConnectedTo;
2324
}
2425

2526
routeIncomingMessages(newMessage) {
@@ -36,32 +37,34 @@ class MessageRouter {
3637
return;
3738
}
3839

39-
const bannedPhrase = this.spamDetection.checkAgainstBannedPhrases(messageContent);
40-
41-
if (bannedPhrase !== false) {
42-
if (bannedPhrase.type === 'mute') {
43-
this.punishmentStream.write(
44-
makeMute(
45-
user,
46-
bannedPhrase.duration,
47-
`${user} muted for using banned phrase(${bannedPhrase.text}).`,
48-
true,
49-
),
50-
);
51-
} else if (bannedPhrase.type === 'ban') {
52-
this.punishmentStream.write(
53-
makeBan(
54-
user,
55-
bannedPhrase.duration,
56-
null,
57-
null,
58-
`${user} banned for using banned phrase(${bannedPhrase.text}).`,
59-
true,
60-
),
61-
);
40+
if (this.chatConnectedTo === 'twitch') {
41+
const bannedPhrase = this.spamDetection.checkAgainstBannedPhrases(messageContent);
42+
43+
if (bannedPhrase !== false) {
44+
if (bannedPhrase.type === 'mute') {
45+
this.punishmentStream.write(
46+
makeMute(
47+
user,
48+
bannedPhrase.duration,
49+
`${user} muted for using banned phrase(${bannedPhrase.text}).`,
50+
true,
51+
),
52+
);
53+
} else if (bannedPhrase.type === 'ban') {
54+
this.punishmentStream.write(
55+
makeBan(
56+
user,
57+
bannedPhrase.duration,
58+
null,
59+
null,
60+
`${user} banned for using banned phrase(${bannedPhrase.text}).`,
61+
true,
62+
),
63+
);
64+
}
65+
this.chatCache.addMessageToRunningList(user, messageContent);
66+
return;
6267
}
63-
this.chatCache.addMessageToRunningList(user, messageContent);
64-
return;
6568
}
6669

6770
const nukedPhrases = this.punishmentCache.getNukedPhrases();

lib/services/banned-phrase-emitter.js

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
const EventEmitter = require('events');
2+
3+
class BannedPhrases extends EventEmitter {
4+
constructor() {
5+
super();
6+
}
7+
8+
addBannedPhrase(phrase) {
9+
this.emit('data', { action: 'add', phrase });
10+
}
11+
12+
removeBannedPhrase(phrase) {
13+
this.emit('data', { action: 'remove', phrase });
14+
}
15+
}
16+
17+
module.exports = BannedPhrases;

lib/services/destinychat.js

+10
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ const {
1212
formatUnmute,
1313
formatBan,
1414
formatUnban,
15+
formatAddPhrase,
16+
formatRemovePhrase,
1517
formatPoll,
1618
} = require('../chat-utils/parse-commands-from-chat');
1719

@@ -119,6 +121,14 @@ class DestinyChat extends EventEmitter {
119121
});
120122
}
121123

124+
sendAddPhrase(phrase) {
125+
this.ws.send(formatAddPhrase(phrase));
126+
}
127+
128+
sendRemovePhrase(phrase) {
129+
this.ws.send(formatRemovePhrase(phrase));
130+
}
131+
122132
handleError(event) {
123133
this.emit('error', event);
124134
}

lib/services/service-index.js

+2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const RedditVote = require('./reddit-vote');
1919
const MessageRelay = require('./message-relay');
2020
const messageMatchingService = require('./message-matching');
2121
const HTMLMetadata = require('./html-metadata');
22+
const BannedPhrases = require('./banned-phrase-emitter')
2223

2324
class Services {
2425
constructor(serviceConfigurations, chatConnectedTo) {
@@ -49,6 +50,7 @@ class Services {
4950
if (chatConnectedTo === 'dgg') {
5051
this.redditVote = new RedditVote(serviceConfigurations.redditVote, this.logger);
5152
}
53+
this.bannedPhrases = new BannedPhrases();
5254
}
5355

5456
prepareAsyncServices() {

0 commit comments

Comments
 (0)