Browse Source

Send help/guide messages to DM when possible

ghorsington 3 years ago
parent
commit
a039229496
3 changed files with 58 additions and 22 deletions
  1. 32 9
      bot/src/plugins/guide.ts
  2. 13 2
      bot/src/plugins/help.ts
  3. 13 11
      bot/src/util.ts

+ 32 - 9
bot/src/plugins/guide.ts

@@ -1,7 +1,8 @@
-import { Message } from "discord.js";
+import { DMChannel, Message, NewsChannel, TextChannel } from "discord.js";
 import { getRepository } from "typeorm";
 import { Guide, GuideType, GuideKeyword } from "@shared/db/entity/Guide";
 import { Event, BotEventData, Command, ICommandData, Plugin } from "src/model/plugin";
+import { tryDo } from "../../../shared/lib/src/common/async_utils";
 
 @Plugin
 export class GuideCommands {
@@ -36,6 +37,23 @@ export class GuideCommands {
             .where("guide.type = :type", { type: guideType })
             .getMany();
 
+        const dmChannelResult = await tryDo(msg.author.createDM());
+        let channel: TextChannel | DMChannel | NewsChannel;
+        if (dmChannelResult.ok){
+            await tryDo(msg.delete());
+            channel = dmChannelResult.result;
+        } else  {
+            channel = msg.channel;
+        }
+
+        const send = async (content: string) => {
+            const result = await tryDo(channel.send(content));
+            if (result.ok)
+                return;
+            channel = msg.channel;
+            await tryDo(channel.send(content));
+        };
+
         const MAX_GUIDES_PER_MSG = 30;
         let guides = `${msg.author.toString()} ${message}\n\`\`\``;
         let guideNum = 0;
@@ -45,7 +63,7 @@ export class GuideCommands {
 
             if (guideNum == MAX_GUIDES_PER_MSG) {
                 guides += "```";
-                await msg.channel.send(guides);
+                await send(guides);
                 guides = "```\n";
                 guideNum = 0;
             }
@@ -53,7 +71,7 @@ export class GuideCommands {
 
         if (guideNum != 0) {
             guides += "```\n\nTo display the guides, ping me with one or more keywords, like `@NoctBot sybaris com`";
-            await msg.channel.send(guides);
+            await send(guides);
         }
     }
 
@@ -70,7 +88,7 @@ export class GuideCommands {
         const guide = await this.matchGuide(parts);
 
         if (guide) {
-            msg.channel.send(guide.content);
+            await tryDo(msg.channel.send(guide.content));
             data.actionsDone = true;
         }
     }
@@ -82,7 +100,8 @@ export class GuideCommands {
         documentation: {
             description: "Creates a new guide of the specified type, the specified keywords and content.",
             example: "make <GUIDE TYPE> <NEWLINE>name: <NAME> <NEWLINE> keywords: <KEYWORDS> <NEWLINE> contents: <CONTENTS>"
-        }
+        },
+        allowDM: true,
     })
     async makeGuide({ message, contents }: ICommandData): Promise<void> {
         const match = contents as RegExpMatchArray;
@@ -161,7 +180,8 @@ export class GuideCommands {
         documentation: {
             example: "delete <guidetype> <keywords>",
             description: "Deletes a guide with the specified keywords"
-        }
+        },
+        allowDM: true,
     })
     async deleteGuide({ message, contents }: ICommandData): Promise<void> {
         const match = contents as RegExpMatchArray;
@@ -204,7 +224,8 @@ export class GuideCommands {
         documentation: { 
             description: "Lists all guides and keywords that trigger them.", 
             example: "guides" 
-        } 
+        },
+        allowDM: true,
     })
     async showGuides({ message }: ICommandData): Promise<void> {
         await this.listGuides(message, "guide", "Here are the guides I have:");
@@ -216,7 +237,8 @@ export class GuideCommands {
         documentation: {
             description: "Lists all memes and keywords that trigger them.", 
             example: "memes"
-        } 
+        },
+        allowDM: true,
     })
     async showMemes({ message }: ICommandData): Promise<void> {
         await this.listGuides(message, "meme", "Here are some random memes I have:");
@@ -228,7 +250,8 @@ export class GuideCommands {
         documentation: {
             description: "Lists all additional keywords the bot reacts to.", 
             example: "misc"
-        } 
+        },
+        allowDM: true,
     })
     async showMisc({ message }: ICommandData): Promise<void> {
         await this.listGuides(message, "misc", "These are some misc stuff I can also do:");

+ 13 - 2
bot/src/plugins/help.ts

@@ -2,15 +2,17 @@ import { isAuthorisedAsync } from "../util";
 import { plgMgr, COMMAND_PREFIX } from "src/main";
 import { Command, ICommandData, Plugin } from "src/model/plugin";
 import { client } from "src/client";
+import { tryDo } from "../../../shared/lib/src/common/async_utils";
 
 @Plugin
 export class Help {
     @Command({
         type: "mention",
-        pattern: "help" 
+        pattern: "help",
+        allowDM: true
     })
     async showHelp({ message }: ICommandData): Promise<void> {
-        const isAuthed = await isAuthorisedAsync(message.member);
+        const isAuthed = await isAuthorisedAsync(message.member ?? message.author);
 
         let baseCommands = "\n";
         let modCommands = "\n";
@@ -32,6 +34,15 @@ export class Help {
         if (isAuthed)
             msg = `${msg}\n👑**Moderator commands**👑\n\`\`\`${modCommands}\`\`\`\n**Prefix commands**\`\`\`${prefixCommands}\`\`\``;
 
+        const dmResult = await tryDo(message.author.createDM());
+
+        if (dmResult.ok) {
+            await tryDo(message.delete());
+            const result = await tryDo(dmResult.result.send(msg));
+            if (result.ok)
+                return;
+        }
+
         message.reply(msg);
     }
 }

+ 13 - 11
bot/src/util.ts

@@ -1,4 +1,4 @@
-import { GuildMember } from "discord.js";
+import { GuildMember, User } from "discord.js";
 import { getRepository, In } from "typeorm";
 import { KnownUser } from "@shared/db/entity/KnownUser";
 import humanizeDuration from "humanize-duration";
@@ -29,7 +29,7 @@ export function isValidImage(fileName?: string | null): boolean {
     return VALID_EXTENSIONS.has(ext);
 }
 
-export async function isAuthorisedAsync(member: GuildMember | null | undefined): Promise<boolean> {
+export async function isAuthorisedAsync(member: GuildMember | User | null | undefined): Promise<boolean> {
     if (!member)
         return false;
 
@@ -43,15 +43,17 @@ export async function isAuthorisedAsync(member: GuildMember | null | undefined):
     if (user && user.canModerate)
         return true;
 
-    const role = await repo.findOne({
-        select: ["userID"],
-        where: {
-            userID: In(member.roles.cache.keyArray()),
-            canModerate: true
-        }
-    });
-    if (role)
-        return true;
+    if (member instanceof GuildMember) {
+        const role = await repo.findOne({
+            select: ["userID"],
+            where: {
+                userID: In(member.roles.cache.keyArray()),
+                canModerate: true
+            }
+        });
+        if (role)
+            return true;
+    }
     return false;
 }