Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix gulag and voteban commands #142

Merged
merged 9 commits into from
Feb 20, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions lib/chat-utils/parse-commands-from-chat.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ function formatUnban(user) {
return `UNBAN ${JSON.stringify({ data: user })}`;
}

function formatPoll(weighted, time, question, options) {
return `STARTPOLL ${JSON.stringify({
weighted,
time,
question,
options,
})}`;
}

function parseMessage(message) {
const parsed = JSON.parse(message.replace('MSG ', ''));
return { user: parsed.nick, roles: parsed.features, message: parsed.data };
Expand Down Expand Up @@ -59,6 +68,7 @@ module.exports = {
formatUnmute,
formatBan,
formatUnban,
formatPoll,
parseWhisper,
formatWhisper,
};
95 changes: 48 additions & 47 deletions lib/commands/implementations/gulag.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,15 @@ const Command = require('../command-interface');
const CommandOutput = require('../command-output');
const { makeBan } = require('../../chat-utils/punishment-helpers');

function isNormalInteger(str) {
const n = Math.floor(Number(str));
return n !== Infinity && String(n) === str && n >= 0;
}
let gulagStarted = false;
function gulag(defaultBanTime) {
return (input, services, rawMessage) => {
if (gulagStarted) {
if (services.messageRelay.pollActive) {
return new CommandOutput(
null,
'Gulag in progress. Please wait for the current vote to finish.',
'Poll in progress. Please wait for the current poll to finish.',
);
}

const {
isPermanent,
parsedDuration,
Expand All @@ -25,65 +21,70 @@ function gulag(defaultBanTime) {
if (parsedUsers.length > 5) {
return new CommandOutput(null, 'Too many users to be sent to the gulag, max of 5.');
}
gulagStarted = true;

const listener = services.messageRelay.startListenerForChatMessages('gulag');
if (listener === false) {
return new CommandOutput(null, 'Something went wrong?? uhh. Restart me.');
}
const votedMap = {};
const users = _.uniq(
parsedUsers.map((name) => {
if (name.toLowerCase() === 'random') {
return services.roleCache.getRecentRandomUsername();
}
return name;
}),
);
const userVotes = users.map((name) => ({ name, value: 0 }));
listener.on('message', (data) => {
if (votedMap[data.user]) {
return;
}
const message = data.message.trim();
if (isNormalInteger(message)) {
const int = parseInt(message, 10);
if (int >= 1 && int <= users.length) {
votedMap[data.user] = true;
userVotes[int - 1].value += 1;
}
}
});
setTimeout(() => {
gulagStarted = false;
listener.on('pollstop', (message) => {
const poll = JSON.parse(message);

services.messageRelay.stopRelay('gulag');
services.messageRelay.sendOutputMessage('Total votes:');
userVotes.forEach((user) => {
services.messageRelay.sendOutputMessage(`${user.name} votes: ${user.value}`);
services.messageRelay.sendOutputMessage('GULAG has ended:');

const winnerVotes =
poll.totals[poll.totals.reduce((max, x, i, arr) => (x > arr[max] ? i : max), 0)];
Mitchdev marked this conversation as resolved.
Show resolved Hide resolved
const winners = [];
const losers = [];
poll.totals.forEach((votes, index) => {
if (votes === winnerVotes) {
winners.push({ user: poll.options[index], votes });
} else {
losers.push({ user: poll.options[index], votes });
}
});
const firstWinner = _.maxBy(userVotes, 'value');
const winners = userVotes.filter((user) => user.value === firstWinner.value);
const losers = userVotes.filter((user) => user.value !== firstWinner.value);
winners.forEach((user) => {
winners.forEach(({ user, votes }) => {
services.messageRelay.sendOutputMessage(
`${user.name} has won the most votes and will be released from the gulag AYAYA`,
`${user} has won the most votes and will be released from the gulag AYAYA . Votes: ${votes}`,
);
});
losers.forEach((user) => {
losers.forEach(({ user, votes }) => {
services.punishmentStream.write(
makeBan(
user.name,
user,
parsedDuration,
false,
isPermanent,
`${user.name} banned through bot by GULAG battle started by ${rawMessage.user}. Votes: ${user.value}`,
`${user} banned through bot by GULAG battle started by ${rawMessage.user}. Votes: ${votes}`,
),
);
});
}, 30500);
const userOrs = users.join(' or ');
});

const users = _.uniq(
parsedUsers.map((name) => {
if (name.toLowerCase() === 'random') {
return services.roleCache.getRecentRandomUsername();
}
return name;
}),
);

services.messageRelay.emit(
'poll',
JSON.stringify({
weighted: false,
time: 30000,
question: `ENTER THE GULAG. Chatters battling it out to not get a ${muteString} ban. Vote KEEP not KICK!?`,
options: users,
}),
);

return new CommandOutput(
null,
`/vote ENTER THE GULAG. Chatters battling it out to not get ${muteString} ban. Vote KEEP not KICK!? ${userOrs} 30s`,
`ENTER THE GULAG. Chatters battling it out to not get a ${muteString} ban. Vote KEEP not KICK!? ${users.join(
' vs ',
)}`,
);
};
}
Expand Down
76 changes: 30 additions & 46 deletions lib/commands/implementations/voteban.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
const _ = require('lodash');
const moment = require('moment');

const Command = require('../command-interface');
Expand All @@ -7,22 +6,15 @@ const { makeBan } = require('../../chat-utils/punishment-helpers');
const basePunishmentHelper = require('../base-punishment-helper');
const formatDuration = require('../../chat-utils/format-duration');

let voteBanStarted = false;
const weightedTranslateMap = {
flair8: 16,
flair3: 8,
flair1: 4,
flair13: 2,
flair9: 2,
};
function voteBan(ipBan, defaultBanTime, weighted) {
return function ban(input, services, rawMessage) {
if (voteBanStarted) {
if (services.messageRelay.pollActive) {
return new CommandOutput(
null,
'Vote ban in progress. Please wait for the current vote to finish.',
'Poll in progress. Please wait for the current poll to finish.',
);
}

const parsedInput = basePunishmentHelper(input, defaultBanTime)[0];
if (parsedInput === false) {
return new CommandOutput(
Expand All @@ -32,53 +24,29 @@ function voteBan(ipBan, defaultBanTime, weighted) {
}
const { isPermanent, userToPunish, parsedDuration, parsedReason } = parsedInput;

voteBanStarted = true;
const listener = services.messageRelay.startListenerForChatMessages('voteban');
if (listener === false) {
return new CommandOutput(null, 'Something went wrong?? uhh. Restart me.');
}
listener.on('pollstop', (message) => {
const poll = JSON.parse(message);

const muteString = isPermanent
? 'PERMANENTLY'
: formatDuration(moment.duration(parsedDuration, 'seconds'));
const votedMap = {};
let yes = 0;
let no = 0;

listener.on('message', (data) => {
if (votedMap[data.user]) {
return;
}
const message = data.message.trim();
if (message.trim() === '1' || message.trim() === '2') {
let votes = 1;
if (weighted) {
votes = _.max(
Object.keys(weightedTranslateMap).map((k) => {
const idx = data.roles.indexOf(k);
if (idx === -1) return 1;
return weightedTranslateMap[k];
}),
);
}
votedMap[data.user] = true;
// eslint-disable-next-line no-unused-expressions
message.trim() === '1' ? (yes += votes) : (no += votes);
}
});

setTimeout(() => {
voteBanStarted = false;
services.messageRelay.stopRelay('voteban');
services.messageRelay.sendOutputMessage('Total votes:');

const yes = poll.totals[poll.options.findIndex((option) => option === 'yes')];
const no = poll.totals[poll.options.findIndex((option) => option === 'no')];
Mitchdev marked this conversation as resolved.
Show resolved Hide resolved

services.messageRelay.sendOutputMessage(`Yes votes: ${yes}`);
services.messageRelay.sendOutputMessage(`No votes: ${no}`);

if (yes <= no) {
services.messageRelay.sendOutputMessage(
`No votes win by ${no - yes} votes, ${userToPunish} is safe for now.. AYAYA `,
);
return;
}

services.punishmentStream.write(
makeBan(
userToPunish,
Expand All @@ -90,13 +58,29 @@ function voteBan(ipBan, defaultBanTime, weighted) {
} Yes votes: ${yes} No Votes: ${no}`,
),
);
}, 30500);
});

const muteString = isPermanent
? 'PERMANENTLY'
: formatDuration(moment.duration(parsedDuration, 'seconds'));

services.messageRelay.emit(
'poll',
JSON.stringify({
weighted,
time: 30000,
question: `Should we ban ${userToPunish} ${
muteString === 'PERMANENTLY' ? muteString : `for ${muteString}`
} ${parsedReason ? ` Reason: ${parsedReason}` : ''}`,
options: ['yes', 'no'],
}),
);

return new CommandOutput(
null,
`/vote Should we ban ${userToPunish} ${
`Should we ban ${userToPunish} ${
muteString === 'PERMANENTLY' ? muteString : `for ${muteString}`
} ${parsedReason ? ` Reason: ${parsedReason}` : ''}? yes or no 30s`,
} ${parsedReason ? ` Reason: ${parsedReason}` : ''}?`,
);
};
}
Expand Down
16 changes: 16 additions & 0 deletions lib/message-routing/chat-service-router.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,15 @@ class ChatServiceRouter {
});
});

this.bot.on('pollstart', () => {
this.messageRelay.pollActive = true;
});

this.bot.on('pollstop', (message) => {
this.messageRelay.pollActive = false;
this.messageRelay.relayMessageToListeners('pollstop', message);
});

this.messageSchedulerStream.on('command', (commandObject) => {
this.bot.sendMessage(commandObject.work().output);
});
Expand All @@ -115,6 +124,13 @@ class ChatServiceRouter {
this.bot.sendMessage(message);
});

this.messageRelay.on('poll', (message) => {
const poll = JSON.parse(message);
if (this.chatToConnectTo === 'dgg') {
this.bot.sendPoll(poll.weighted, poll.time, poll.question, poll.options);
}
});

this.punishmentStream.on('data', (punishmentObject) => {
switch (punishmentObject.type) {
case 'unmute':
Expand Down
2 changes: 1 addition & 1 deletion lib/message-routing/message-router.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class MessageRouter {
const messageContent = newMessage.message;
getReporter().incrementCounter(METRIC_NAMES.MESSAGE_RATE, 1);
// No api to get roles, we gotta STORE IT
this.messageRelay.relayMessageToListeners(newMessage);
this.messageRelay.relayMessageToListeners('message', newMessage);
Mitchdev marked this conversation as resolved.
Show resolved Hide resolved

this.roleCache.addUserRoles(user, roles);

Expand Down
12 changes: 12 additions & 0 deletions lib/services/destinychat.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const {
formatUnmute,
formatBan,
formatUnban,
formatPoll,
} = require('../chat-utils/parse-commands-from-chat');

class DestinyChat extends EventEmitter {
Expand Down Expand Up @@ -65,6 +66,13 @@ class DestinyChat extends EventEmitter {
});
}
}

if (_.startsWith(event.data, 'POLLSTART')) {
this.emit('pollstart', event.data.replace('POLLSTART ', ''));
}
if (_.startsWith(event.data, 'POLLSTOP')) {
this.emit('pollstop', event.data.replace('POLLSTOP ', ''));
}
}

sendMessage(message) {
Expand Down Expand Up @@ -99,6 +107,10 @@ class DestinyChat extends EventEmitter {
this.ws.send(formatUnban(punished.user));
}

sendPoll(weighted, time, question, options) {
this.ws.send(formatPoll(weighted, time, question, options));
}

sendMultiLine(message) {
message.forEach((newLineMessage) => {
if (!_.isEmpty(newLineMessage)) {
Expand Down
5 changes: 3 additions & 2 deletions lib/services/message-relay.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ class MessageRelay extends EventEmitter {
constructor() {
super();
this.listeners = {};
this.pollActive = false;
Mitchdev marked this conversation as resolved.
Show resolved Hide resolved
}

sendOutputMessage(message) {
Expand All @@ -20,13 +21,13 @@ class MessageRelay extends EventEmitter {
return this.listeners[listenerKey];
}

relayMessageToListeners(message) {
relayMessageToListeners(type, message) {
if (_.keys(this.listeners).length === 0) {
return;
}

_.forEach(this.listeners, (listener) => {
listener.emit('message', message);
listener.emit(type, message);
});
}

Expand Down
Loading