Skip to content

Commit b816bf7

Browse files
authored
Merge pull request #142 from destinygg/gulag-voteban-fix
Fix gulag and voteban commands
2 parents ea02e6c + b5c5537 commit b816bf7

File tree

11 files changed

+212
-127
lines changed

11 files changed

+212
-127
lines changed

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

+10
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,15 @@ function formatUnban(user) {
2626
return `UNBAN ${JSON.stringify({ data: user })}`;
2727
}
2828

29+
function formatPoll(weighted, time, question, options) {
30+
return `STARTPOLL ${JSON.stringify({
31+
weighted,
32+
time,
33+
question,
34+
options,
35+
})}`;
36+
}
37+
2938
function parseMessage(message) {
3039
const parsed = JSON.parse(message.replace('MSG ', ''));
3140
return { user: parsed.nick, roles: parsed.features, message: parsed.data };
@@ -59,6 +68,7 @@ module.exports = {
5968
formatUnmute,
6069
formatBan,
6170
formatUnban,
71+
formatPoll,
6272
parseWhisper,
6373
formatWhisper,
6474
};

lib/commands/implementations/breaking-news.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ function breakingNews(defaultMaxAge) {
5353
const formattedMaxAge = formatDuration(moment.duration(maxAge, 'seconds'));
5454

5555
const listener = services.messageRelay.startListenerForChatMessages('breakingnews');
56-
listener.on('message', (data) => {
56+
listener.on('msg', (data) => {
5757
const message = data.message.trim().toLowerCase();
5858
if (state !== 'all' && !services.messageMatching.mentionsUser(message, mentionUser)) return;
5959
if (!services.messageMatching.hasLink(message)) return;

lib/commands/implementations/gulag.js

+74-43
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,32 @@ const Command = require('../command-interface');
33
const CommandOutput = require('../command-output');
44
const { makeBan } = require('../../chat-utils/punishment-helpers');
55

6-
function isNormalInteger(str) {
7-
const n = Math.floor(Number(str));
8-
return n !== Infinity && String(n) === str && n >= 0;
9-
}
10-
let gulagStarted = false;
116
function gulag(defaultBanTime) {
7+
const pollDuration = 30000;
8+
9+
let failSafeTimeout = null;
10+
let gulagActive = false;
11+
1212
return (input, services, rawMessage) => {
13-
if (gulagStarted) {
13+
if (gulagActive) {
1414
return new CommandOutput(
1515
null,
16-
'Gulag in progress. Please wait for the current vote to finish.',
16+
'Gulag in progress. Please wait for the current gulag to finish.',
1717
);
1818
}
19+
1920
const {
2021
isPermanent,
2122
parsedDuration,
2223
muteString,
2324
users: parsedUsers,
2425
} = services.gulag.parseInput(input, defaultBanTime);
26+
2527
if (parsedUsers.length > 5) {
2628
return new CommandOutput(null, 'Too many users to be sent to the gulag, max of 5.');
2729
}
28-
gulagStarted = true;
29-
const listener = services.messageRelay.startListenerForChatMessages('gulag');
30-
if (listener === false) {
31-
return new CommandOutput(null, 'Something went wrong?? uhh. Restart me.');
32-
}
33-
const votedMap = {};
30+
31+
// FIXME: There's a chance that a random user is already in the list, reducing the number of expected users.
3432
const users = _.uniq(
3533
parsedUsers.map((name) => {
3634
if (name.toLowerCase() === 'random') {
@@ -39,52 +37,85 @@ function gulag(defaultBanTime) {
3937
return name;
4038
}),
4139
);
42-
const userVotes = users.map((name) => ({ name, value: 0 }));
43-
listener.on('message', (data) => {
44-
if (votedMap[data.user]) {
45-
return;
46-
}
47-
const message = data.message.trim();
48-
if (isNormalInteger(message)) {
49-
const int = parseInt(message, 10);
50-
if (int >= 1 && int <= users.length) {
51-
votedMap[data.user] = true;
52-
userVotes[int - 1].value += 1;
53-
}
40+
41+
const listener = services.messageRelay.startListenerForChatMessages('gulag');
42+
if (listener === false) {
43+
return new CommandOutput(null, 'Something went wrong?? uhh. Restart me.');
44+
}
45+
46+
listener.on('err', (message) => {
47+
const error = JSON.parse(message);
48+
if (error.description === 'activepoll' && !gulagActive) {
49+
clearTimeout(failSafeTimeout);
50+
services.messageRelay.stopRelay('gulag');
51+
services.messageRelay.sendOutputMessage(
52+
'Poll in progress. Please wait for the current poll to finish.',
53+
);
5454
}
5555
});
56-
setTimeout(() => {
57-
gulagStarted = false;
56+
57+
listener.on('pollstart', () => {
58+
gulagActive = true;
59+
services.messageRelay.sendOutputMessage(
60+
`ENTER THE GULAG. Chatters battling it out to not get a ${muteString} ban. Vote KEEP not KICK!? ${users.join(
61+
' vs ',
62+
)}`,
63+
);
64+
65+
// Fail-safe
66+
failSafeTimeout = setTimeout(() => {
67+
gulagActive = false;
68+
services.messageRelay.stopRelay('gulag');
69+
}, pollDuration + 5000);
70+
});
71+
72+
listener.on('pollstop', (message) => {
73+
clearTimeout(failSafeTimeout);
74+
gulagActive = false;
5875
services.messageRelay.stopRelay('gulag');
59-
services.messageRelay.sendOutputMessage('Total votes:');
60-
userVotes.forEach((user) => {
61-
services.messageRelay.sendOutputMessage(`${user.name} votes: ${user.value}`);
76+
77+
services.messageRelay.sendOutputMessage('GULAG has ended:');
78+
79+
const poll = JSON.parse(message);
80+
const winnerVotes = Math.max(...poll.totals);
81+
const winners = [];
82+
const losers = [];
83+
poll.totals.forEach((votes, index) => {
84+
if (votes === winnerVotes) {
85+
winners.push({ user: poll.options[index], votes });
86+
} else {
87+
losers.push({ user: poll.options[index], votes });
88+
}
6289
});
63-
const firstWinner = _.maxBy(userVotes, 'value');
64-
const winners = userVotes.filter((user) => user.value === firstWinner.value);
65-
const losers = userVotes.filter((user) => user.value !== firstWinner.value);
66-
winners.forEach((user) => {
90+
winners.forEach(({ user, votes }) => {
6791
services.messageRelay.sendOutputMessage(
68-
`${user.name} has won the most votes and will be released from the gulag AYAYA`,
92+
`${user} has won the most votes and will be released from the gulag AYAYA . Votes: ${votes}`,
6993
);
7094
});
71-
losers.forEach((user) => {
95+
losers.forEach(({ user, votes }) => {
7296
services.punishmentStream.write(
7397
makeBan(
74-
user.name,
98+
user,
7599
parsedDuration,
76100
false,
77101
isPermanent,
78-
`${user.name} banned through bot by GULAG battle started by ${rawMessage.user}. Votes: ${user.value}`,
102+
`${user} banned through bot by GULAG battle started by ${rawMessage.user}. Votes: ${votes}`,
79103
),
80104
);
81105
});
82-
}, 30500);
83-
const userOrs = users.join(' or ');
84-
return new CommandOutput(
85-
null,
86-
`/vote ENTER THE GULAG. Chatters battling it out to not get ${muteString} ban. Vote KEEP not KICK!? ${userOrs} 30s`,
106+
});
107+
108+
services.messageRelay.emit(
109+
'poll',
110+
JSON.stringify({
111+
weighted: false,
112+
time: pollDuration,
113+
question: `ENTER THE GULAG. Chatters battling it out to not get a ${muteString} ban. Vote KEEP not KICK!?`,
114+
options: users,
115+
}),
87116
);
117+
118+
return new CommandOutput(null, '');
88119
};
89120
}
90121
module.exports = {

lib/commands/implementations/mutelinks.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ function mutelinks(defaultPunishmentDuration) {
5252
const listener = services.messageRelay.startListenerForChatMessages('mutelinks');
5353

5454
const formattedDuration = formatDuration(moment.duration(muteDuration, 'seconds'));
55-
listener.on('message', (data) => {
55+
listener.on('msg', (data) => {
5656
const message = data.message.trim().toLowerCase();
5757
if (state !== 'all' && !services.messageMatching.mentionsUser(message, mentionUser)) return;
5858
if (!services.messageMatching.hasLink(message)) return;

lib/commands/implementations/voteban.js

+65-52
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,90 @@
1-
const _ = require('lodash');
21
const moment = require('moment');
3-
2+
const _ = require('lodash');
43
const Command = require('../command-interface');
54
const CommandOutput = require('../command-output');
65
const { makeBan } = require('../../chat-utils/punishment-helpers');
76
const basePunishmentHelper = require('../base-punishment-helper');
87
const formatDuration = require('../../chat-utils/format-duration');
98

10-
let voteBanStarted = false;
11-
const weightedTranslateMap = {
12-
flair8: 16,
13-
flair3: 8,
14-
flair1: 4,
15-
flair13: 2,
16-
flair9: 2,
17-
};
189
function voteBan(ipBan, defaultBanTime, weighted) {
10+
const pollDuration = 30000;
11+
12+
let failSafeTimeout = null;
13+
let votebanActive = false;
14+
1915
return function ban(input, services, rawMessage) {
20-
if (voteBanStarted) {
16+
if (votebanActive) {
2117
return new CommandOutput(
2218
null,
23-
'Vote ban in progress. Please wait for the current vote to finish.',
19+
'Vote ban in progress. Please wait for the current vote ban to finish.',
2420
);
2521
}
22+
2623
const parsedInput = basePunishmentHelper(input, defaultBanTime)[0];
24+
2725
if (parsedInput === false) {
2826
return new CommandOutput(
2927
null,
3028
'Could not parse the duration. Usage: "!voteban {amount}{m,h,d,w}OR{perm} {user}" !voteban 1d Destiny',
3129
);
3230
}
31+
3332
const { isPermanent, userToPunish, parsedDuration, parsedReason } = parsedInput;
33+
const muteString = isPermanent
34+
? 'PERMANENTLY'
35+
: formatDuration(moment.duration(parsedDuration, 'seconds'));
3436

35-
voteBanStarted = true;
3637
const listener = services.messageRelay.startListenerForChatMessages('voteban');
3738
if (listener === false) {
3839
return new CommandOutput(null, 'Something went wrong?? uhh. Restart me.');
3940
}
4041

41-
const muteString = isPermanent
42-
? 'PERMANENTLY'
43-
: formatDuration(moment.duration(parsedDuration, 'seconds'));
44-
const votedMap = {};
45-
let yes = 0;
46-
let no = 0;
47-
48-
listener.on('message', (data) => {
49-
if (votedMap[data.user]) {
50-
return;
51-
}
52-
const message = data.message.trim();
53-
if (message.trim() === '1' || message.trim() === '2') {
54-
let votes = 1;
55-
if (weighted) {
56-
votes = _.max(
57-
Object.keys(weightedTranslateMap).map((k) => {
58-
const idx = data.roles.indexOf(k);
59-
if (idx === -1) return 1;
60-
return weightedTranslateMap[k];
61-
}),
62-
);
63-
}
64-
votedMap[data.user] = true;
65-
// eslint-disable-next-line no-unused-expressions
66-
message.trim() === '1' ? (yes += votes) : (no += votes);
42+
listener.on('err', (message) => {
43+
const error = JSON.parse(message);
44+
if (error.description === 'activepoll' && !votebanActive) {
45+
clearTimeout(failSafeTimeout);
46+
services.messageRelay.stopRelay('voteban');
47+
services.messageRelay.sendOutputMessage(
48+
'Poll in progress. Please wait for the current poll to finish.',
49+
);
6750
}
6851
});
6952

70-
setTimeout(() => {
71-
voteBanStarted = false;
53+
listener.on('pollstart', () => {
54+
votebanActive = true;
55+
services.messageRelay.sendOutputMessage(
56+
`Should we ban ${userToPunish} ${
57+
muteString === 'PERMANENTLY' ? muteString : `for ${muteString}`
58+
} ${parsedReason ? ` Reason: ${parsedReason}` : ''}?`,
59+
);
60+
61+
// Fail-safe
62+
failSafeTimeout = setTimeout(() => {
63+
votebanActive = false;
64+
services.messageRelay.stopRelay('voteban');
65+
}, pollDuration + 5000);
66+
});
67+
68+
listener.on('pollstop', (message) => {
69+
clearTimeout(failSafeTimeout);
70+
votebanActive = false;
7271
services.messageRelay.stopRelay('voteban');
72+
7373
services.messageRelay.sendOutputMessage('Total votes:');
74-
services.messageRelay.sendOutputMessage(`Yes votes: ${yes}`);
75-
services.messageRelay.sendOutputMessage(`No votes: ${no}`);
76-
if (yes <= no) {
74+
75+
const poll = JSON.parse(message);
76+
const votes = _.zipObject(poll.options, poll.totals);
77+
78+
services.messageRelay.sendOutputMessage(`Yes votes: ${votes.yes}`);
79+
services.messageRelay.sendOutputMessage(`No votes: ${votes.no}`);
80+
81+
if (votes.yes <= votes.no) {
7782
services.messageRelay.sendOutputMessage(
78-
`No votes win by ${no - yes} votes, ${userToPunish} is safe for now.. AYAYA `,
83+
`No votes win by ${votes.no - votes.yes} votes, ${userToPunish} is safe for now.. AYAYA `,
7984
);
8085
return;
8186
}
87+
8288
services.punishmentStream.write(
8389
makeBan(
8490
userToPunish,
@@ -87,17 +93,24 @@ function voteBan(ipBan, defaultBanTime, weighted) {
8793
isPermanent,
8894
`${userToPunish} banned through bot by a VOTE BAN started by ${rawMessage.user}. ${
8995
parsedReason ? `Reason: ${parsedReason}` : ''
90-
} Yes votes: ${yes} No Votes: ${no}`,
96+
} Yes votes: ${votes.yes} No Votes: ${votes.no}`,
9197
),
9298
);
93-
}, 30500);
99+
});
94100

95-
return new CommandOutput(
96-
null,
97-
`/vote Should we ban ${userToPunish} ${
98-
muteString === 'PERMANENTLY' ? muteString : `for ${muteString}`
99-
} ${parsedReason ? ` Reason: ${parsedReason}` : ''}? yes or no 30s`,
101+
services.messageRelay.emit(
102+
'poll',
103+
JSON.stringify({
104+
weighted,
105+
time: pollDuration,
106+
question: `Should we ban ${userToPunish} ${
107+
muteString === 'PERMANENTLY' ? muteString : `for ${muteString}`
108+
} ${parsedReason ? ` Reason: ${parsedReason}` : ''}`,
109+
options: ['yes', 'no'],
110+
}),
100111
);
112+
113+
return new CommandOutput(null, '');
101114
};
102115
}
103116

0 commit comments

Comments
 (0)