123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- import { parseYaml } from "../util";
- import { Command, ICommandData, Plugin } from "src/model/plugin";
- import { tryDo } from "@shared/common/async_utils";
- import * as t from "io-ts";
- import { logger } from "src/logging";
- import { getRepository } from "typeorm";
- import { GiveRoleMessage } from "@shared/db/entity/GiveRoleMessage";
- import { Message, MessageReaction, ReactionCollector, ReactionEmoji, TextChannel, User } from "discord.js";
- import { client } from "src/client";
- const ReactRoleMessageParams = t.type({
- message: t.string,
- roleId: t.string
- });
- const REACT_EMOTE = "⭐";
- const MSG_COLOR = 9830318;
- @Plugin
- export class GiveRoleForReact {
- @Command({
- type: "mention",
- pattern: "add role message",
- documentation: {
- description: "Add role giver message",
- example: "add role message { message: \"This is a role!\", roleId: \"0237894783782\" }"
- },
- allowDM: false,
- auth: true
- })
- async makeRoleMessage({ message, contents }: ICommandData): Promise<void> {
- const textContent = (contents as string).substring("add role message".length).trim();
-
- tryDo(message.delete());
- const opts = parseYaml(ReactRoleMessageParams, textContent);
- if (!opts.ok) {
- await this.sendDM(message.author, `Sorry, I don't understand the command! Got the following errors: ${opts.errors.join("\n")}`);
- return;
- }
- const params = opts.result;
- if (!message.guild?.roles.cache.has(params.roleId)) {
- await this.sendDM(message.author, "Sorry, the role ID is not a valid role on the server!");
- return;
- }
- const msgSendResult = await tryDo(message.channel.send({
- embed: {
- title: `React with ${REACT_EMOTE} to gain role`,
- description: params.message,
- color: MSG_COLOR
- }
- }));
- if (!msgSendResult.ok) {
- logger.error(`GiveRoleForReact: failed to create message because ${msgSendResult.error}`);
- return;
- }
- const msg = msgSendResult.result;
- await msg.react(REACT_EMOTE);
- const roleGiveMessageRepo = getRepository(GiveRoleMessage);
- if (!msg.guild) {
- logger.error("GiveRoleForReact: tried to set up role react for DMs (this should never happen!)");
- return;
- }
-
- await roleGiveMessageRepo.save({
- messageId: msg.id,
- guildId: msg.guild.id,
- channelId: msg.channel.id,
- roleToGive: params.roleId
- });
- this.initReactCollector(msg, params.roleId);
- }
- private initReactCollector(msg: Message, role: string) {
- const check = (reaction: MessageReaction) => {
- return reaction.emoji.name == REACT_EMOTE;
- };
- const collector = new ReactionCollector(msg, check, {
- dispose: true
- });
- const guild = msg.guild;
- if (!guild) {
- throw new Error("Tried to initialize role collector for non-guild channel.");
- }
- collector.on("collect", async (_, user) => {
- if (user.bot) {
- return;
- }
- const gu = guild.member(user);
- if (!gu) {
- return;
- }
- const result = await tryDo(gu.roles.add(role));
- if (!result.ok) {
- logger.error("GiveRoleForReact: Can't add role %s to user %s: %s", role, gu.id, result.error);
- }
- });
- collector.on("remove", async (_, user) => {
- if (user.bot) {
- return;
- }
- const gu = guild.member(user);
- if (!gu) {
- return;
- }
- const result = await tryDo(gu.roles.remove(role));
- if (!result.ok) {
- logger.error("GiveRoleForReact: Can't remove role %s to user %s: %s", role, gu.id, result.error);
- }
- });
- }
- private async sendDM(usr: User, messageText: string) {
- const dmResult = await tryDo(usr.createDM());
- if (dmResult.ok) {
- tryDo(dmResult.result.send(messageText));
- }
- }
- async start(): Promise<void> {
- logger.info("Initializing role give messages");
- const roleGiveMessageRepo = getRepository(GiveRoleMessage);
- const reactMessages = await roleGiveMessageRepo.find();
- const staleEntities = [];
- for (const reactMessage of reactMessages) {
- const guildResult = await tryDo(client.bot.guilds.fetch(reactMessage.guildId));
- if (!guildResult.ok) {
- staleEntities.push(reactMessage);
- continue;
- }
- const guild = guildResult.result;
- const channel = guild.channels.resolve(reactMessage.channelId);
- if (!channel || !(channel instanceof TextChannel)) {
- staleEntities.push(reactMessage);
- continue;
- }
- const msgResult = await tryDo(channel.messages.fetch(reactMessage.messageId));
- if (!msgResult.ok) {
- staleEntities.push(reactMessage);
- continue;
- }
-
- this.initReactCollector(msgResult.result, reactMessage.roleToGive);
- }
- await roleGiveMessageRepo.remove(staleEntities);
- }
- }
|