meshcore.js
Guides

Read the arguments

Declare what a command takes and get it typed in the handler.

/heard 6 repeater lists the repeaters heard in the last six hours. Both values are optional and have a default.

commands/heard.ts
export default new CommandBuilder()
  .setName('heard')
  .setDescription('Nodes heard recently')
  .addIntegerArg((arg) => arg.setName('hours').setDescription('How far back').setMin(1).setMax(48).setDefault(1))
  .addChoiceArg((arg) =>
    arg.setName('kind').setDescription('Node kind').setChoices('chat', 'repeater').setDefault('chat'),
  )
  .setHandler((ctx) => {
    // ctx.args is { hours: number; kind: 'chat' | 'repeater' }
    const since = Date.now() - ctx.args.hours * 3_600_000;
    const heard = ctx.client.contacts.cache.filter(
      (contact) => contact.type === ctx.args.kind && contact.lastSeen.getTime() > since,
    );
    return ctx.reply(`${heard.size} ${ctx.args.kind} nodes in the last ${ctx.args.hours}h`);
  });

What happens

Each add*Arg call declares one argument. ctx.args is typed from these calls, so hours is a number and kind is 'chat' | 'repeater' without a cast.

A value outside the range, or a kind that is not in the list, never reaches the handler. The bot answers with the usage line instead.

Values are split on spaces. Double quotes keep a value with spaces together. A string argument with setRest() takes the rest of the line.

Go further

On this page