meshcore.js
Guides

Write a plugin

Group commands that belong together, configure them, reload them from the radio.

A poll on the channel and a vote in DM. Both share the same state, so they live in one plugin.

polls-plugin.ts
export const polls = new PluginBuilder<{ channel: string }>()
  .setName('polls')
  .setDescription('One yes/no poll at a time')
  .setBricks((client, { channel }) => {
    const votes = new Map<string, 'yes' | 'no'>();

    return [
      new CommandBuilder()
        .setName('poll')
        .setDescription('Open a poll on the channel')
        .addStringArg((arg) => arg.setName('question').setRequired().setRest())
        .setHandler(async (ctx) => {
          votes.clear();
          await client.channels.get(channel)?.send(`📊 ${ctx.args.question} (/vote yes|no)`);
        }),
      new CommandBuilder()
        .setName('vote')
        .setDescription('Vote on the open poll')
        .addChoiceArg((arg) => arg.setName('answer').setChoices('yes', 'no').setRequired())
        .setHandler((ctx) => {
          votes.set(ctx.author.name, ctx.args.answer);
          return ctx.reply(`${votes.size} votes so far`);
        }),
    ];
  });
plugins/polls.ts
export default polls.configure({ channel: '#club' });

What happens

setBricks() is a factory. It runs when the plugin loads and on every reload, with the client and the options. State kept in its closure is reset on reload.

configure() returns a copy carrying the options. The file under plugins/ exports that copy, and the loader registers it. The same plugin can be configured twice with two names.

/plugins reload polls from a DM rebuilds the bricks. If the new version fails, the previous bricks keep running.

Go further

On this page