stickers.ts 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. import { Plugin, Event, BotEventData, Command, ICommandData } from "src/model/plugin";
  2. import { readdirSync, statSync } from "fs";
  3. import { join, basename, extname } from "path";
  4. import { Message } from "discord.js";
  5. import { logger } from "src/logging";
  6. import { tryDo } from "@shared/common/async_utils";
  7. const STICKERS_PATH = "./stickers";
  8. const STICKERS_PREFIX = "!";
  9. const STICKERS_PER_ROW = 5;
  10. const ROWS_PER_MESSAGE = 30;
  11. @Plugin
  12. export class Stickers {
  13. stickers: Record<string, string> = {};
  14. @Event("message")
  15. async onMessage(data: BotEventData, msg: Message): Promise<void> {
  16. if (data.actionsDone)
  17. return;
  18. const lowerContent = msg.cleanContent.trim().toLowerCase();
  19. if (!lowerContent.startsWith(STICKERS_PREFIX))
  20. return;
  21. const stickerName = lowerContent.substr(1);
  22. if (!(stickerName in this.stickers))
  23. return;
  24. const deleteResult = await tryDo(msg.delete());
  25. if (!deleteResult.ok) {
  26. logger.error("Stickers: failed to delete message %s from user %s. Reason: %s", msg.id, msg.author.id, deleteResult.error);
  27. }
  28. const sendResult = await tryDo(msg.channel.send({
  29. content: `${msg.author.toString()} *sent a sticker:*`,
  30. files: [this.stickers[stickerName]]
  31. }));
  32. if (!sendResult.ok) {
  33. logger.error("Stickers: failed to send sticker to channel %s. Reason: %s", msg.channel.id, sendResult.error);
  34. }
  35. data.actionsDone = true;
  36. }
  37. @Command({
  38. type: "mention",
  39. pattern: "stickers",
  40. auth: false,
  41. documentation: { description: "Lists all available stickers", example: "stickers" }
  42. })
  43. async listStickers({ message }: ICommandData): Promise<void> {
  44. const stickerNames = Object.keys(this.stickers)
  45. .filter(s => Object.prototype.hasOwnProperty.call(this.stickers, s));
  46. const maxLength = stickerNames.map(s => s.length).reduce((prev, cur) => Math.max(prev, cur), 0);
  47. const m = stickerNames.reduce((prev, cur, i) => `${prev}!${cur}${" ".repeat(maxLength - cur.length + 2)}${(i + 1) % STICKERS_PER_ROW == 0 ? "\n" : ""}`, "");
  48. let toSend = `${message.author.toString()}, I have the following stickers:\n\`\`\``;
  49. const rows = m.split("\n");
  50. for (let i = 0; i < rows.length; i++) {
  51. toSend += `${rows[i]}\n`;
  52. if (i != 0 && i % ROWS_PER_MESSAGE == 0) {
  53. toSend += "```";
  54. await message.channel.send(toSend);
  55. toSend = "```\n";
  56. }
  57. }
  58. toSend += "```\n";
  59. toSend += "To use stickers, simply use their name. Example: !hackermaid";
  60. await message.channel.send(toSend);
  61. }
  62. async start(): Promise<void> {
  63. const files = readdirSync(STICKERS_PATH).filter(f => !statSync(join(STICKERS_PATH, f)).isDirectory());
  64. for (const file of files)
  65. this.stickers[basename(file, extname(file)).toLowerCase()] = join(STICKERS_PATH, file);
  66. logger.info("Found %s stickers", Object.keys(this.stickers).length);
  67. }
  68. }