aboutsummaryrefslogtreecommitdiffstats
path: root/src/config.js
diff options
context:
space:
mode:
authorElvis Claros Castro <elvis@claros.ar>2026-09-26 19:26:33 -0300
committerElvis Claros Castro <elvis@claros.ar>2026-09-26 19:26:33 -0300
commitd80640d01eeb84907e36ff4af33add9081eda17c (patch)
tree27698b34e06e28d111c2196700015d9c82f78274 /src/config.js
downloadwa-cli-main.tar.gz
wa-cli-main.zip
wa-cli: WhatsApp from the terminal, with a neomutt Maildir bridgeHEADmain
Diffstat (limited to 'src/config.js')
-rw-r--r--src/config.js82
1 files changed, 82 insertions, 0 deletions
diff --git a/src/config.js b/src/config.js
new file mode 100644
index 0000000..d29ada4
--- /dev/null
+++ b/src/config.js
@@ -0,0 +1,82 @@
+// Paths, accounts and user config.
+//
+// Everything follows XDG, split per account (like gws with several accounts):
+// config ~/.config/wa-cli/config.json, hooks/
+// session ~/.local/share/wa-cli/<account>/ (LocalAuth: Chrome profile)
+// state ~/.local/state/wa-cli/<account>/ (pid, daemon log)
+// media ~/.local/share/wa-cli/<account>/media/
+// socket $XDG_RUNTIME_DIR/wa-cli/<account>.sock
+
+import fs from 'node:fs';
+import os from 'node:os';
+import path from 'node:path';
+
+const env = process.env;
+const HOME = os.homedir();
+const XDG_CONFIG = env.XDG_CONFIG_HOME || path.join(HOME, '.config');
+const XDG_DATA = env.XDG_DATA_HOME || path.join(HOME, '.local/share');
+const XDG_STATE = env.XDG_STATE_HOME || path.join(HOME, '.local/state');
+const XDG_CACHE = env.XDG_CACHE_HOME || path.join(HOME, '.cache');
+const RUNTIME = env.XDG_RUNTIME_DIR || path.join(os.tmpdir(), `wa-cli-${process.getuid()}`);
+
+const ACCOUNT_RE = /^[A-Za-z0-9_-]+$/;
+
+export const VERSION = JSON.parse(
+ fs.readFileSync(new URL('../package.json', import.meta.url), 'utf8'),
+).version;
+
+export function accountName(flag) {
+ const name = flag || env.WA_CLI_ACCOUNT || 'default';
+ if (!ACCOUNT_RE.test(name)) {
+ throw Object.assign(new Error(`invalid account name: ${name} (only [A-Za-z0-9_-])`), { code: 'EINVAL' });
+ }
+ return name;
+}
+
+export function paths(account) {
+ const configDir = env.WA_CLI_CONFIG_DIR || path.join(XDG_CONFIG, 'wa-cli');
+ const dataDir = path.join(env.WA_CLI_DATA_DIR || path.join(XDG_DATA, 'wa-cli'), account);
+ const stateDir = path.join(XDG_STATE, 'wa-cli', account);
+ return {
+ configDir,
+ configFile: path.join(configDir, 'config.json'),
+ hooksDir: path.join(configDir, 'hooks'),
+ dataDir,
+ mediaDir: path.join(dataDir, 'media'),
+ stateDir,
+ pidFile: path.join(stateDir, 'daemon.pid'),
+ logFile: path.join(stateDir, 'daemon.log'),
+ cacheDir: path.join(XDG_CACHE, 'wa-cli'),
+ socket: env.WA_CLI_SOCKET || path.join(RUNTIME, 'wa-cli', `${account}.sock`),
+ };
+}
+
+const DEFAULTS = {
+ autostart: true, // the CLI starts the daemon if it is not running
+ readyTimeoutMs: 120000, // how long a command waits for the session to be ready
+ startTimeoutMs: 180000, // if WhatsApp Web does not load within this time, the daemon exits (and is restarted)
+ hooks: true, // ejecutar ~/.config/wa-cli/hooks/<evento>
+ hookTimeoutMs: 60000,
+ browserName: 'wa-cli', // shows as "wa-cli (Linux)" under Linked devices
+ deviceName: 'Linux',
+ puppeteer: { headless: true },
+};
+
+// config.json: { ...globals, "accounts": { "<account>": { ...overrides } } }
+export function loadConfig(account) {
+ const p = paths(account);
+ let file = {};
+ try {
+ file = JSON.parse(fs.readFileSync(p.configFile, 'utf8'));
+ } catch (e) {
+ if (e.code !== 'ENOENT') {
+ throw Object.assign(new Error(`${p.configFile}: ${e.message}`), { code: 'EINVAL' });
+ }
+ }
+ const { accounts = {}, ...global } = file;
+ const cfg = { ...DEFAULTS, ...global, ...(accounts[account] || {}) };
+ cfg.puppeteer = { ...DEFAULTS.puppeteer, ...global.puppeteer, ...accounts[account]?.puppeteer };
+ cfg.wamail = { ...global.wamail, ...accounts[account]?.wamail };
+ if (env.WA_CLI_AUTOSTART !== undefined) cfg.autostart = !/^(0|false|no)$/i.test(env.WA_CLI_AUTOSTART);
+ return cfg;
+}