Skip to content

Instantly share code, notes, and snippets.

@eritbh
Created June 5, 2022 21:08
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eritbh/afa6d25ef18f1c21d2f4b9b9646b400d to your computer and use it in GitHub Desktop.
Save eritbh/afa6d25ef18f1c21d2f4b9b9646b400d to your computer and use it in GitHub Desktop.

awaitButton.ts

A sample interaction awaiter that specifically only cares about button interactions with globally unique custom IDs.

Can be modified to respond differently to other conditions (i.e. only letting a specific user click the button, or handling other sorts of components). If that's what you want to do, you'll want to modify the buttons data structure to hold information about your custom conditions, and add logic within the interactionCreate listener to only call the associated resolver function when necessary.

This is a naive implementation, with several potential issues:

  • listening is a global variable, not directly associated with the client the listener is being added to (though you really shouldn't have multiple clients in your project anyway so it's probably fine)
  • Using an object for buttons means that only one person can listen for a specific customID at a time; this code will just overwrite the old listener if it's called a second time with the same ID, causing the old one to time out no matter what.
  • Using an object for buttons is also not very extensible; if you want to hold more general conditions, such as filtering by user in addition to customID, you may want to change it to be e.g. an array of objects, where each object holds its condition information in addition to the resolve function, and the event listener loops through all those objects, calling the resolve function wherever the condition matches the interaction

Usage

channel.createMessage({
  content: 'Hello',
  components: [
    {
      type: Constants.ComponentTypes.ACTION_ROW,
      components: [
        {
          type: Constants.ComponentTypes.BUTTON,
          style: Constants.ButtonStyles.PRIMARY,
          custom_id: 'some unique ID',
          label: 'Click me!',
        },
      ],
    },
  ],
});

try {
  const interaction = await awaitButton(bot, 'some unique ID');
    console.log('Button pressed by', interaction.user!.username);
  } catch (error) {
    console.log('button wasn not pressed within 30 seconds');
  }
}
import {Client, ComponentInteraction, Constants} from 'eris';
// a promise resolver that takes a component interaction
type ResolveToInteraction = (d: ComponentInteraction) => void;
const buttons: Record<string, ResolveToInteraction> = {};
// whether or not the required listener has been registered yet (ensures only one listener is used)
let listening = false;
export function awaitButton (client: Client, customID: string, timeout = 30 * 1000) {
// add an interactionCreate listener if there isn't one already
if (!listening) {
client.on('interactionCreate', interaction => {
// we only care about component interactions from button components
if (interaction.type !== Constants.InteractionTypes.MESSAGE_COMPONENT) return;
if (interaction.data.component_type !== Constants.ComponentTypes.BUTTON) return;
// we only care about buttons with custom IDs we were asked to track
if (!buttons[interaction.data.custom_id]) return;
// whoever was waiting for this interaction,
buttons[interaction.data.custom_id](interaction);
delete buttons[interaction.data.custom_id];
});
listening = true;
}
// return a promise to the caller
return new Promise((resolve, reject) => {
// record that the caller is waiting for the button to be clicked
buttons[customID] = resolve;
// time out if the button isn't clicked within some time
setTimeout(() => {
// if the button was already clicked, we don't need to reject
if (!buttons[customID]) return;
// stop listening for the button and reject the promise
delete buttons[customID];
reject(new Error('Timed out'));
}, timeout);
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment