react.ts 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. import { isAuthorised } from "../util";
  2. import client from "../client";
  3. import { ICommand } from "./command";
  4. import { getRepository } from "typeorm";
  5. import { MessageReaction } from "../entity/MessageReaction";
  6. import { KnownUser } from "../entity/KnownUser";
  7. import { ReactionType, ReactionEmote } from "../entity/ReactionEmote";
  8. const pattern = /^react to\s+"([^"]+)"\s+with\s+\<:[^:]+:([^\>]+)\>$/i;
  9. async function getRandomEmotes(allowedTypes: ReactionType[]) {
  10. let reactionEmotesRepo = getRepository(ReactionEmote);
  11. return await reactionEmotesRepo.query(`
  12. select reactionId
  13. from ( select type, reactionId
  14. from reaction_emote
  15. where type in (?)
  16. order by type, random() )
  17. group by type`, [ allowedTypes ]) as string[];
  18. }
  19. export default {
  20. commands: [
  21. {
  22. pattern: "react to",
  23. action: async (msg, s) => {
  24. if (!isAuthorised(msg.member))
  25. return;
  26. let contents = pattern.exec(s);
  27. if (contents != null) {
  28. let reactable = contents[1].trim().toLowerCase();
  29. let reactionEmoji = contents[2];
  30. if (!client.emojis.has(reactionEmoji)) {
  31. msg.channel.send(`${msg.author.toString()} I cannot react with this emoji :(`);
  32. return;
  33. }
  34. let repo = getRepository(MessageReaction);
  35. let message = repo.create({
  36. message: reactable,
  37. reactionEmoteId: reactionEmoji
  38. });
  39. await repo.save(message);
  40. msg.channel.send(`${msg.author.toString()} Added reaction!`);
  41. }
  42. }
  43. },
  44. {
  45. pattern: "remove reaction to",
  46. action: async (msg, s) => {
  47. if (!isAuthorised(msg.member))
  48. return;
  49. let content = s.substring("remove reaction to ".length).trim().toLowerCase();
  50. let repo = getRepository(MessageReaction);
  51. let result = await repo.delete({ message: content });
  52. if (result.affected == 0) {
  53. msg.channel.send(`${msg.author.toString()} No such reaction available!`);
  54. return;
  55. }
  56. msg.channel.send(`${msg.author.toString()} Removed reaction!`);
  57. }
  58. },
  59. {
  60. pattern: "reactions",
  61. action: async msg => {
  62. let reactionsRepo = getRepository(MessageReaction);
  63. let messages = await reactionsRepo.find({
  64. select: [ "message" ]
  65. });
  66. let reactions = messages.reduce((p, c) => `${p}\n${c.message}`, "");
  67. msg.channel.send(`I'll react to the following messages:\n\`\`\`${reactions}\n\`\`\``);
  68. }
  69. }
  70. ],
  71. documentation: {
  72. "react to \"<message>\" with <emote>": {
  73. auth: true,
  74. description: "React to <message> with <emote>."
  75. },
  76. "remove reaction to <message>": {
  77. auth: true,
  78. description: "Stops reacting to <message>."
  79. },
  80. "reactions": {
  81. auth: false,
  82. description: "Lists all known messages this bot can react to."
  83. }
  84. },
  85. onMessage: async (actionsDone, msg, content) => {
  86. if (actionsDone)
  87. return false;
  88. let lowerContent = content.toLowerCase();
  89. let reactionRepo = getRepository(MessageReaction);
  90. let usersRepo = getRepository(KnownUser);
  91. let message = await reactionRepo.findOne({ message: lowerContent });
  92. if(message) {
  93. msg.react(client.emojis.get(message.reactionEmoteId));
  94. return true;
  95. }
  96. if (msg.mentions.users.size == 0)
  97. return false;
  98. let knownUsers = await usersRepo.find({
  99. select: [ "mentionReactionType" ],
  100. where: [...msg.mentions.users.map(u => ({ userId: u.id }))]
  101. });
  102. if(knownUsers.length == 0)
  103. return false;
  104. let reactionEmoteTypes = new Set<ReactionType>();
  105. for(let user of knownUsers) {
  106. if(user.mentionReactionType == ReactionType.NONE)
  107. continue;
  108. reactionEmoteTypes.add(user.mentionReactionType);
  109. }
  110. let randomEmotes = await getRandomEmotes([...reactionEmoteTypes]);
  111. if(randomEmotes.length == 0)
  112. return false;
  113. for(let emote in randomEmotes)
  114. await msg.react(client.emojis.find(e => e.id == emote));
  115. return true;
  116. },
  117. onIndirectMention: async (actionsDone, msg) => {
  118. if (actionsDone)
  119. return false;
  120. let emoteType = ReactionType.ANGERY;
  121. let repo = getRepository(KnownUser);
  122. let knownUser = await repo.findOne({
  123. select: [ "mentionReactionType" ],
  124. where: [{userID: msg.id}]
  125. });
  126. if(!knownUser || knownUser.mentionReactionType == ReactionType.NONE)
  127. return false;
  128. emoteType = knownUser.mentionReactionType;
  129. let emotes = await getRandomEmotes([ emoteType ]);
  130. if(emotes.length != 1)
  131. return false;
  132. let emote = client.emojis.find(e => e.id == emotes[0]);
  133. if (!emote) {
  134. console.log(`WARNING: Emote ${emotes[0]} no longer is valid. Deleting invalid emojis from the list...`);
  135. let emotesRepo = getRepository(ReactionEmote);
  136. emotesRepo.delete({ reactionId: emotes[0] });
  137. return false;
  138. }
  139. msg.channel.send(emote.toString());
  140. return true;
  141. }
  142. } as ICommand;