From 0225712f8bb0cd953f38b2632a85a3ccdc4912bd Mon Sep 17 00:00:00 2001 From: Rob van der Leek <5324924+robvanderleek@users.noreply.github.com> Date: Tue, 30 Jun 2026 13:55:53 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20=E2=9C=A8=20Added=20--timeout=20flag?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 22 ++++++++++++++-- src/index.ts | 69 ++++++++++++++++++++++++++++++++++--------------- src/whatsapp.ts | 2 ++ 3 files changed, 70 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index f1971c1..cd3c480 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ working without notice. * [Installation](#installation) * [Usage](#usage) -* [Configuration](#configuration) +* [Global configuration options](#global-configuration-options) * [Troubleshooting](#troubleshooting) * [FAQ](#faq) * [Development](#development) @@ -350,7 +350,16 @@ To get the WhatsApp ID of the logged in user: npx mudslide@latest me ``` -# Configuration +# Global configuration options + +The global configuration options must precede the command. +For example: + +```shell +npx mudslide@latest --timeout 3 send me 'hello world' +``` + +## Location of cache folder By default WhatsApp credentials are cached in a folder located in the user's home directory. This folder is `~/.local/share/mudslide` on Linux & macOS and @@ -372,6 +381,15 @@ export HTTPS_PROXY=http://USER:PASS@proxy.server.com:80 npx mudslide@latest --proxy login ``` +## Timeout + +The default timeout for commands is 10 seconds. This duration can be changed +using the `--timeout ` flag: + +```shell +npx mudslide@latest --timeout 3 send me 'hello world' +``` + # Troubleshooting In case Mudslide does not give any output or does not behave as expected, try diff --git a/src/index.ts b/src/index.ts index 1ba81a9..87d2d3a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,5 @@ #!/usr/bin/env node -import {program} from "commander"; +import {Command, Option, program} from "commander"; import {globalOptions, loginWithPairingCode, loginWithQrCode, logout, mudslideFooter} from "./whatsapp"; import { listGroupParticipants, @@ -13,6 +13,7 @@ import { sendPoll } from "./commands"; import {bootstrap} from 'global-agent'; +import signale from "signale"; const packageJson = require('../package.json'); @@ -42,68 +43,94 @@ program.on('option:proxy', () => { // @ts-ignore global.GLOBAL_AGENT.HTTPS_PROXY = process.env.HTTPS_PROXY; }); -program - .command('login') - .description('Login to WhatsApp') - .option('--pairing-code', 'Use pairing code instead of QR code') - .action((options) => options.pairingCode ? loginWithPairingCode() : loginWithQrCode()); -program - .command('logout') - .description('Logout from WhatsApp') - .action(() => logout()); - -function configureCommands() { +program.addOption(new Option('--timeout ', 'Command timeout').default(10).argParser(parseInt)); + +program.hook('preAction', (command: Command) => { + const timeout = command.getOptionValue('timeout'); + setTimeout(() => { + signale.error('Action timed out'); + process.exit(1); + }, timeout * 1000); +}); + +function configureBasicCommands() { + program + .command('login') + .description('Login to WhatsApp') + .option('--pairing-code', 'Use pairing code instead of QR code') + .action((options) => options.pairingCode ? loginWithPairingCode() : loginWithQrCode()); + + program + .command('logout') + .description('Logout from WhatsApp') + .action(() => logout()); + program .command('me') .description('Show current user details') .action(() => me()); - program - .command('groups') - .description('List all your groups') - .action(() => listGroups()); +} + +function configureSendCommands() { program .command('send ') .description('Send message') .action((recipient, message, options) => sendMessage(recipient, message, options)); + program .command('send-image ') .option('--caption ', 'Caption text') .description('Send image file') .action((recipient, file, options) => sendImage(recipient, file, options)); + program .command('send-file ') .option('--caption ', 'Caption text') .option('--type ', 'File type', 'document') .description('Send file') .action((recipient, file, options) => sendFile(recipient, file, options)); + program .command('send-location ') .allowUnknownOption() .description('Send location') .action((recipient, latitude, longitude) => sendLocation(recipient, latitude, longitude)); + program .command('send-poll ') .option('--item ', 'Poll item (repeatable option)', (val, prev: Array) => prev.concat([val]), []) .option('--selectable ', 'Number of selectable items', '1') .description('Send poll') .action((recipient, name, options) => sendPoll(recipient, name, options)); +} + +function configureGroupCommands() { + program + .command('groups') + .description('List all your groups') + .action(() => listGroups()); + + program + .command('list-group ') + .description('List group participants') + .action((groupId) => listGroupParticipants(groupId)); + program .command('add-to-group ') .allowUnknownOption() .description('Add group participant') .action((groupId, phoneNumber) => mutateGroup(groupId, phoneNumber, 'add')); + program .command('remove-from-group ') .allowUnknownOption() .description('Remove group participant') .action((groupId, phoneNumber) => mutateGroup(groupId, phoneNumber, 'remove')); - program - .command('list-group ') - .description('List group participants') - .action((groupId) => listGroupParticipants(groupId)); } -configureCommands(); +configureBasicCommands(); +configureSendCommands(); +configureGroupCommands(); program.addHelpText('after', ` Examples: diff --git a/src/whatsapp.ts b/src/whatsapp.ts index 67c967f..3c85d26 100644 --- a/src/whatsapp.ts +++ b/src/whatsapp.ts @@ -47,6 +47,8 @@ export async function initWASocket(message?: string): Promise { const os = process.platform === 'darwin' ? 'macOS' : process.platform === 'win32' ? 'Windows' : 'Linux'; const {version} = await fetchLatestWaWebVersion({}); const socket = makeWASocket({ + connectTimeoutMs: 3_000, + defaultQueryTimeoutMs: 6_000, logger: pino({level: globalOptions.logLevel}), auth: state, browser: [os, 'Chrome', '10.15.0'],