dragonbane

ZSR Interactive Session

Mar 6th, 2021 (edited)
657
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. const userSessionEmojiTable = [":one:", ":two:"];
  2. var userSessionsInput = {};
  3.  
  4. function onMessage(message) {
  5.     //Somewhere in the code
  6.     if (message.content == "!assignToRace") {
  7.         startInteractiveBotSession("raceAssign", message).then(() => {
  8.             console.log("session ended, delete message");
  9.             message.delete();
  10.         });
  11.     }
  12. }
  13.  
  14. async function startInteractiveBotSession(name, message) {
  15.  
  16.     try {
  17.         //All the interactive session commands we support
  18.         switch (name) {
  19.             case "raceAssign": {
  20.                 return await raceAssignSession(message);
  21.             }
  22.          }
  23.     }
  24.     catch (ex) {
  25.         console.log("Aborted session cause:", ex);
  26.     }
  27. }
  28.  
  29. async function raceAssignSession(message) {
  30.  
  31.   try{
  32.  
  33.   //Say hello
  34.   let messagePointer = await renderRaceAssignEmbed("intro", message);
  35.  
  36.   //Wait for yes or no
  37.   let userResponse = await waitForUserInput(messagePointer, message.member);
  38.  
  39.   //Verify to which number the emoji belongs if reaction or otherwise look at the message content and do something/branch off
  40.   let pressedNo = userResponse.isReaction && userResponse.data == 2 || !userResponse.isReaction && userResponse.data.content == "No";
  41.  
  42.   if (pressedNo) {
  43.     await renderRaceAssignEmbed("aborted", messagePointer, true);
  44.     return;
  45.   }
  46.  
  47.   //User wants to continue. Time to select the person
  48.   messagePointer = await renderRaceAssignEmbed("selectPerson", messagePointer, true, { user: message.member });
  49.  
  50.   //Wait for person selection
  51.   let userResponsePerson = await waitForUserInput(messagePointer, message.member);
  52.  
  53.   if (userResponsePerson.isReaction) {
  54.     //User selected a pre-defined person from our list
  55.   }
  56.   else {
  57.     //User entered a completely new name presumably. Verify and get name from userResponsePerson.data (= the message)
  58.   }
  59.  
  60.   console.log("Session finished. Set data to replicant now!");
  61.   await renderRaceAssignEmbed("finished", messagePointer, true, { selectedPerson: "Trez" });
  62.   } catch (ex) {
  63.    if (typeof(ex) == "string" and ex == "no_response") {
  64.       await renderRaceAssignEmbed("aborted", messagePointer, true);
  65.    }
  66.   }
  67.  }
  68.  
  69. async function renderRaceAssignEmbed(phase, message, editExisting = false, extraInfo = null) {
  70.  
  71.     let embed;
  72.     let menuOptionsCount;
  73.  
  74.     //All our session phases and possibilities we need an embed for
  75.     switch (phase) {
  76.         case "intro": { //user just started
  77.             embed = { text: "hey there, here is my start embed. My options are explained here. Press 1 for yes and 2 for no" };
  78.             menuOptionsCount = 2;
  79.             break;
  80.         }
  81.         case "selectPerson": { //user selects a person
  82.             embed = { text: `hey there ${extraInfo.user.name}, now select from this list of runners or enter a new name!` };
  83.             menuOptionsCount = 5;
  84.             break;
  85.         }
  86.         case "finished": { //user finished the process
  87.             embed = { text: `Thank you! You selected: ${extraInfo.selectedPerson}` };
  88.             menuOptionsCount = 0;
  89.             break;
  90.         }
  91.         case "aborted": { //user aborted the process
  92.             embed = { text: "Too bad. Process aborted!" };
  93.             menuOptionsCount = 0;
  94.             break;
  95.         }
  96.     }
  97.  
  98.     return await renderUserSessionEmbed(message, embed, menuOptionsCount, editExisting);
  99. }
  100.  
  101. async function renderUserSessionEmbed(message, embed, menuOptionsCount, editExisting) {
  102.  
  103.     let messagePointer;
  104.  
  105.     if (!editExisting) {
  106.         messagePointer = await message.reply(embed);
  107.     }
  108.     else {
  109.         await message.reactions.removeAll();
  110.         messagePointer = await message.edit(embed);
  111.     }
  112.  
  113.     //Add reaction emojis to posted or edited message
  114.     let reactions = [];
  115.  
  116.     for (let i = 0; i < menuOptionsCount; i++) {
  117.  
  118.         let emoji = emojiIndexToName(i); //1-x number reaction emoji
  119.  
  120.         reactions.push(messagePointer.react(emoji));        
  121.     }
  122.  
  123.     await Promise.all(reactions);
  124.  
  125.     return messagePointer;
  126. }
  127.  
  128. function waitForUserInput(message, user) {
  129.  
  130.     return new Promise((resolve, reject) => {
  131.  
  132.         let timeout = setTimeout(() => {
  133.             delete userSessionsInput[message.id];
  134.             reject("no_response");
  135.         }, 10000);
  136.  
  137.         userSessionsInput[message.id] = { message, user, resolve, reject, timeout };
  138.     });
  139. }
  140.  
  141. function emojiIndexToName(index) {
  142.    return userSessionEmojiTable[index];
  143. }
  144.  
  145. function emojiNameToIndex(emoji) {
  146.    return userSessionEmojiTable.indexOf(emoji) + 1;
  147. }
  148.  
  149. //Client Events
  150. bot.on("messageReactionAdd", (messageReaction, user) => {
  151.  
  152.     //Check for active user session reaction
  153.     for (let value of Object.values(userSessionsInput)) {
  154.  
  155.         let channelMessage = value.message;
  156.         let channelUser = value.user;
  157.  
  158.         if (messageReaction.message.id == channelMessage.id && user.id == channelUser.id) {
  159.  
  160.             if (value.timeout)
  161.                 clearTimeout(value.timeout);
  162.  
  163.             value.resolve({ isReaction: true, data: emojiNameToIndex(messageReaction.emoji.name) });
  164.             delete userSessionsInput[channelMessage.id];
  165.         }
  166.     }
  167. });
  168.  
  169. bot.on("message", (message) => {
  170.  
  171.     //Check for active user session reply
  172.     for (let value of Object.values(userSessionsInput)) {
  173.  
  174.         let channelMessage = value.message;
  175.         let channelUser = value.user;
  176.  
  177.         if (channelMessage.channel.id == message.channel.id && channelUser.id == message.member.id) {
  178.  
  179.             if (value.timeout)
  180.                 clearTimeout(value.timeout);
  181.  
  182.             value.resolve({ isReaction: false, data: message });
  183.             delete userSessionsInput[channelMessage.id];
  184.         }
  185.     }
  186.  
  187.     //The entire rest of the existing ZSR message handling code
  188.     onMessage(message);
  189. });
  190.  
Advertisement
Add Comment
Please, Sign In to add comment