1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
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;
}
|