Skip to content

Commit

Permalink
Added ability for bot to handle break role
Browse files Browse the repository at this point in the history
  • Loading branch information
hasanlatch007 committed Nov 26, 2021
1 parent d93b481 commit aec5f2a
Show file tree
Hide file tree
Showing 5 changed files with 251 additions and 109 deletions.
44 changes: 44 additions & 0 deletions src/programs/menu/break-handler/addBreak.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import prisma from "../../../prisma";
import { GuildMember, DMChannel } from "discord.js";
import { textLog } from "../../../common/moderator";
import state from "../../../common/state";
import Tools from "../../../common/tools";
import { removeIgnore, logger, handleError, emojiCollector } from "../common";

export const addBreakRole = async (
member: GuildMember,
dmChannel: DMChannel
) => {
const confirmationMessage = await dmChannel.send(
"It looks like you want a little break! It is understandable you can get it by clicking on the :sloth: emoji below. You can send me !menu again to remove it.\n**BE ADVISED: THIS COMMAND CAN ONLY BE USED EVERY 24 HOURS**"
);

state.ignoredGroupDMs.push(dmChannel.id);

const breakRole = Tools.getRoleByName("Break", member.guild);
await confirmationMessage.react("🦥");

const reaction = await emojiCollector(confirmationMessage, "🦥");

if (reaction) {
try {
removeIgnore(dmChannel);
await confirmationMessage.delete();
await member.roles.add(breakRole);
await prisma.usersOnBreak.create({ data: { userId: member.id } });
dmChannel.send("Enjoy your break!");
return;
} catch (e) {
logger.error("Failed to update break status", e);
removeIgnore(dmChannel);
await textLog(`I could not give <@${member.id}> the break role!`);
dmChannel.send(
"Looks like I couldn't give you the break role, I informed the Support team about it, in the meantime you can manually ask one of the Moderators!"
);
return;
}
}

removeIgnore(dmChannel);
await handleError(confirmationMessage, dmChannel);
};
61 changes: 61 additions & 0 deletions src/programs/menu/break-handler/removeBreak.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { UsersOnBreak } from "@yes-theory-fam/database/client";
import prisma from "../../../prisma";
import { GuildMember, DMChannel } from "discord.js";
import { textLog } from "../../../common/moderator";
import state from "../../../common/state";
import Tools from "../../../common/tools";
import {
isCooldownDone,
emojiCollector,
removeIgnore,
logger,
handleError,
} from "../common";

export const removeBreakRole = async (
member: GuildMember,
userData: UsersOnBreak,
dmChannel: DMChannel
) => {
const checkTime = await isCooldownDone(userData);

if (!checkTime) {
dmChannel.send(
"I'm sorry it hasn't been 24 hours since you used this command! If you really want the break role removed you can contact one of our moderators!"
);
return;
}

state.ignoredGroupDMs.push(dmChannel.id);

const breakRole = Tools.getRoleByName("Break", member.guild);
const confirmationMessage = await dmChannel.send(
"It looks like you're ready to rejoin the server! Once you're ready click on the green check below!"
);
await confirmationMessage.react("✅");

const reaction = await emojiCollector(confirmationMessage, "✅");

if (reaction) {
try {
await prisma.usersOnBreak.delete({ where: { userId: userData.userId } });
await member.roles.remove(breakRole);
await dmChannel.send(
"Your break role was removed, we're happy to have you back!"
);
removeIgnore(dmChannel);
return;
} catch (e) {
logger.error("Failed to update break status", e);
removeIgnore(dmChannel);
await textLog(`I could not remove <@${member.id}> break role!`);
await dmChannel.send(
"Looks like I had a little hiccup trying to remove your role, I've contacted Support about your little issue! Sorry in advance."
);
return;
}
}

removeIgnore(dmChannel);
await handleError(confirmationMessage, dmChannel);
};
65 changes: 65 additions & 0 deletions src/programs/menu/common.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { UsersOnBreak } from "@yes-theory-fam/database/client";
import prisma from "../../prisma";
import {
Message,
DMChannel,
CollectorFilter,
MessageReaction,
User,
} from "discord.js";
import state from "../../common/state";
import { createYesBotLogger } from "../../log";

export const mainOptionsEmojis = ["👶", "🦥"];
export const allCollectedEmojis = ["👶", "🦥", "✅", "🚫"];

export const logger = createYesBotLogger("programs", "DmMenu");

export const handleError = async (
optionsMessage: Message,
dmChannel: DMChannel
) => {
removeIgnore(dmChannel);

dmChannel.send(
"Because of technical reasons I can only wait 60 seconds for a reaction. I removed the other message to not confuse you. If you need anything from me, just drop me a message!"
);
await optionsMessage.delete();
};

export const isOnBreak = async (userId: string) => {
return await prisma.usersOnBreak.findFirst({ where: { userId } });
};

export const isCooldownDone = async (
userData: UsersOnBreak
): Promise<boolean> => {
const twentyFourHours = 24 * 60 * 60 * 1000;
const userCoolDownTime = userData.addedAt;
return Date.now() - Number(userCoolDownTime) > twentyFourHours;
};

export const removeIgnore = (channel: DMChannel) => {
const index = state.ignoredGroupDMs.indexOf(channel.id);
if (index > -1) {
state.ignoredGroupDMs.splice(index, 1);
}
};

export const emojiCollector = async (
optionsMessage: Message,
emoji?: string
) => {
const filter: CollectorFilter<[MessageReaction, User]> = (reaction, user) =>
allCollectedEmojis.includes(reaction.emoji.name) && !user.bot;

const reactions = await optionsMessage.awaitReactions({
filter,
time: 60000,
max: 1,
});
if (reactions.size === 0) throw "No reactions";

if (!emoji) return reactions.first();
return reactions.find((e) => e.emoji.toString() === emoji);
};
131 changes: 22 additions & 109 deletions src/programs/menu/dm-menu.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,21 @@
import {
CollectorFilter,
DMChannel,
Message,
MessageReaction,
User,
} from "discord.js";
import { DMChannel, Message } from "discord.js";
import { getMember } from "../../common/moderator";
import state from "../../common/state";
import {
Command,
CommandHandler,
DiscordEvent,
EventLocation,
} from "../../event-distribution";
import { getMember, textLog } from "../../common/moderator";
import { createYesBotLogger } from "../../log";

const logger = createYesBotLogger("programs", "DmMenu");

const removeIgnore = (channel: DMChannel) => {
const index = state.ignoredGroupDMs.indexOf(channel.id);
if (index > -1) {
state.ignoredGroupDMs.splice(index, 1);
}
};

const availableEmojiOptions = ["👶", "🦥"];
import { addBreakRole } from "./break-handler/addBreak";
import { removeBreakRole } from "./break-handler/removeBreak";
import {
emojiCollector,
handleError,
isOnBreak,
mainOptionsEmojis,
} from "./common";
import { nameCollector } from "./nameChange";

@Command({
event: DiscordEvent.MESSAGE,
Expand All @@ -44,13 +35,20 @@ class ShowMenu implements CommandHandler<DiscordEvent.MESSAGE> {
return;
}

const userOnBreak = await isOnBreak(member.id);

if (userOnBreak) {
await removeBreakRole(member, userOnBreak, dmChannel);
return;
}

if (state.ignoredGroupDMs.includes(dmChannel.id)) return;

const optionsMessage = await message.reply(
"Hey, I'm just a bot! Most of what I can do, I do on the YesFam discord, so talk to me there instead! I can help you change your name, though, if you're new around here. Click the :baby: if you want to change your name! Or if you feel like you need a break you can click on the :sloth:"
);

availableEmojiOptions.forEach(
mainOptionsEmojis.forEach(
async (emoji) => await optionsMessage.react(emoji)
);

Expand All @@ -60,6 +58,9 @@ class ShowMenu implements CommandHandler<DiscordEvent.MESSAGE> {
switch (reactions.emoji.toString()) {
case "👶":
await nameCollector(dmChannel, message);
break;
case "🦥":
await addBreakRole(member, dmChannel);
}
} catch (err) {
await handleError(optionsMessage, dmChannel);
Expand All @@ -68,91 +69,3 @@ class ShowMenu implements CommandHandler<DiscordEvent.MESSAGE> {
await optionsMessage.delete();
}
}

const proposeNameChange = async (name: string, botMessage: Message) => {
await botMessage.reply(
"Perfect! I've sent your name request to the mods, hopefully they answer soon! In the meantime, you're free to roam around the server and explore. Maybe post an introduction to get started? :grin:"
);
const message = `Username: ${botMessage.author.toString()} would like to rename to "${name}". Allow?`;
try {
const sentMessage = await textLog(message);
sentMessage.react("✅").then(() => sentMessage.react("🚫"));
sentMessage
.awaitReactions({
filter: (_, user: User) => {
return !user.bot;
},
max: 1,
time: 6000000,
errors: ["time"],
})
.then((collected) => {
const reaction = collected.first();
switch (reaction.emoji.toString()) {
case "✅":
const member = getMember(botMessage.author.id);
member.setNickname(name);
sentMessage.delete();
textLog(`${botMessage.author.toString()} was renamed to ${name}.`);
break;
case "🚫":
sentMessage.delete();
textLog(
`${botMessage.author.toString()} was *not* renamed to ${name}.`
);
break;

default:
break;
}
});
} catch (err) {
logger.error("(proposeNameChange) Error changing name: ", err);
}
};

const nameCollector = async (dmChannel: DMChannel, message: Message) => {
const requestMessage = await dmChannel.send(
"Okay, what's your name then? Please only respond with your name like Henry or Julie, that makes things easier for the Supports! :upside_down:"
);
state.ignoredGroupDMs.push(dmChannel.id);
const nameMessage = await dmChannel.awaitMessages({
filter: (message) => !message.author.bot,
time: 60000,
max: 1,
});
removeIgnore(dmChannel);

if (nameMessage.size === 0) {
requestMessage.delete();
throw "No response";
}

const requestedName = nameMessage.first().content;
proposeNameChange(requestedName, message);
await requestMessage.delete();
};

const emojiCollector = async (optionsMessage: Message) => {
const filter: CollectorFilter<[MessageReaction, User]> = (reaction, user) =>
availableEmojiOptions.includes(reaction.emoji.name) && !user.bot;

const reactions = await optionsMessage.awaitReactions({
filter,
time: 60000,
max: 1,
});
if (reactions.size === 0) throw "No reactions";

return reactions.first();
};

const handleError = async (optionsMessage: Message, dmChannel: DMChannel) => {
removeIgnore(dmChannel);

dmChannel.send(
"Because of technical reasons I can only wait 60 seconds for a reaction. I removed the other message to not confuse you. If you need anything from me, just drop me a message!"
);

await optionsMessage.delete();
};
59 changes: 59 additions & 0 deletions src/programs/menu/nameChange.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { Message, DMChannel } from "discord.js";
import { textLog, getMember } from "../../common/moderator";
import state from "../../common/state";
import { emojiCollector, logger, removeIgnore } from "./common";

export const proposeNameChange = async (name: string, botMessage: Message) => {
await botMessage.reply(
"Perfect! I've sent your name request to the mods, hopefully they answer soon! In the meantime, you're free to roam around the server and explore. Maybe post an introduction to get started? :grin:"
);
const message = `Username: ${botMessage.author.toString()} would like to rename to "${name}". Allow?`;
try {
const sentMessage = await textLog(message);
await sentMessage.react("✅").then(() => sentMessage.react("🚫"));

const reaction = await emojiCollector(sentMessage);

switch (reaction.emoji.toString()) {
case "✅":
const member = getMember(botMessage.author.id);
member.setNickname(name);
sentMessage.delete();
textLog(`${botMessage.author.toString()} was renamed to ${name}.`);
break;
case "🚫":
sentMessage.delete();
textLog(
`${botMessage.author.toString()} was *not* renamed to ${name}.`
);
break;

default:
break;
}
} catch (err) {
logger.error("(proposeNameChange) Error changing name: ", err);
}
};

export const nameCollector = async (dmChannel: DMChannel, message: Message) => {
const requestMessage = await dmChannel.send(
"Okay, what's your name then? Please only respond with your name like Henry or Julie, that makes things easier for the Supports! :upside_down:"
);
state.ignoredGroupDMs.push(dmChannel.id);
const nameMessage = await dmChannel.awaitMessages({
filter: (message) => !message.author.bot,
time: 60000,
max: 1,
});
removeIgnore(dmChannel);

if (nameMessage.size === 0) {
requestMessage.delete();
throw "No response";
}

const requestedName = nameMessage.first().content;
proposeNameChange(requestedName, message);
await requestMessage.delete();
};

0 comments on commit aec5f2a

Please sign in to comment.