botforje 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +381 -0
- package/dist/action/action.js +44 -0
- package/dist/action/catalog.js +40 -0
- package/dist/action/cooldown.js +60 -0
- package/dist/action/executor.js +23 -0
- package/dist/action/template.js +13 -0
- package/dist/action/types.js +2 -0
- package/dist/action/webhook.js +36 -0
- package/dist/actions/action.js +26 -0
- package/dist/actions/cooldown.js +66 -0
- package/dist/actions/request.js +40 -0
- package/dist/api/routes/auth.js +56 -0
- package/dist/api/routes/bots.js +51 -0
- package/dist/api/routes/config.js +24 -0
- package/dist/api/routes/health.js +15 -0
- package/dist/api/routes/index.js +14 -0
- package/dist/api/routes/messages.js +69 -0
- package/dist/api/routes/sessions.js +97 -0
- package/dist/api/routes/status.js +38 -0
- package/dist/api/server.js +153 -0
- package/dist/auth/service.js +102 -0
- package/dist/boot/fleet.js +207 -0
- package/dist/bot/bot.js +30 -0
- package/dist/bot/fleet.js +211 -0
- package/dist/bot/fuzzy.js +20 -0
- package/dist/bot/mapper.js +47 -0
- package/dist/bot/types.js +2 -0
- package/dist/bot/validation.js +38 -0
- package/dist/bot.js +31 -0
- package/dist/cli/create-bot.js +84 -0
- package/dist/cli.js +138 -0
- package/dist/commands/auth.js +200 -0
- package/dist/commands/create-bot.js +64 -0
- package/dist/commands/guide.js +563 -0
- package/dist/commands/lock.js +73 -0
- package/dist/commands/status.js +145 -0
- package/dist/commands/unlock.js +88 -0
- package/dist/commands/validate.js +19 -0
- package/dist/config/mapper.js +152 -0
- package/dist/config/schema.js +2 -0
- package/dist/config/validation.js +705 -0
- package/dist/config/watcher.js +145 -0
- package/dist/config/yaml.js +197 -0
- package/dist/fleet.js +247 -0
- package/dist/flow/executor.js +286 -0
- package/dist/flow/flow.js +2 -0
- package/dist/flow/mapper.js +72 -0
- package/dist/flow/state.js +115 -0
- package/dist/flow/types.js +2 -0
- package/dist/graph/executor.js +294 -0
- package/dist/graph/graph.js +2 -0
- package/dist/graph/state.js +118 -0
- package/dist/helpers/data.js +42 -0
- package/dist/helpers/fuzzy.js +30 -0
- package/dist/helpers/logger.js +89 -0
- package/dist/helpers/validation.js +38 -0
- package/dist/index.js +92 -0
- package/dist/messages/contracts.js +2 -0
- package/dist/messages/inbox.js +58 -0
- package/dist/messages/outbox.js +136 -0
- package/dist/services/auto-response.js +62 -0
- package/dist/services/cooldown.js +60 -0
- package/dist/services/fleet.js +207 -0
- package/dist/services/flow-executor.js +195 -0
- package/dist/services/flow-state.js +118 -0
- package/dist/services/inbox.js +50 -0
- package/dist/services/message-handler.js +78 -0
- package/dist/services/message-queue.js +138 -0
- package/dist/services/outbox.js +138 -0
- package/dist/services/session.js +118 -0
- package/dist/services/webhook.js +87 -0
- package/dist/utils/logger.js +89 -0
- package/dist/utils/webhook.js +36 -0
- package/dist/validation/validate.js +592 -0
- package/dist/whatsapp/client.js +293 -0
- package/dist/whatsapp/session.js +158 -0
- package/dist/whatsapp/types.js +109 -0
- package/dist/whatsapp/whatsapp.js +109 -0
- package/package.json +97 -0
- package/scripts/postinstall.js +45 -0
- package/scripts/preuninstall.js +48 -0
- package/scripts/setup-systemd.js +91 -0
- package/service/botforje.service.template +25 -0
package/package.json
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "botforje",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Create powerful WhatsApp bots with YAML configuration",
|
|
5
|
+
"jest": {
|
|
6
|
+
"preset": "ts-jest",
|
|
7
|
+
"testEnvironment": "node",
|
|
8
|
+
"roots": [
|
|
9
|
+
"<rootDir>/src",
|
|
10
|
+
"<rootDir>/tests/unit",
|
|
11
|
+
"<rootDir>/tests/integration"
|
|
12
|
+
],
|
|
13
|
+
"testMatch": [
|
|
14
|
+
"**/__tests__/**/*.test.ts",
|
|
15
|
+
"**/?(*.)+(spec|test).ts"
|
|
16
|
+
],
|
|
17
|
+
"collectCoverageFrom": [
|
|
18
|
+
"src/**/*.ts",
|
|
19
|
+
"!src/**/*.d.ts"
|
|
20
|
+
]
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"whatsapp",
|
|
24
|
+
"whatsapp-web",
|
|
25
|
+
"bot",
|
|
26
|
+
"automation",
|
|
27
|
+
"service",
|
|
28
|
+
"systemd",
|
|
29
|
+
"chatbot",
|
|
30
|
+
"cli",
|
|
31
|
+
"yaml",
|
|
32
|
+
"no-code"
|
|
33
|
+
],
|
|
34
|
+
"author": {
|
|
35
|
+
"name": "Félix Sánchez (@felixzsh)",
|
|
36
|
+
"email": "felix.sanchez.dev@gmail.com",
|
|
37
|
+
"url": "https://github.com/felixzsh"
|
|
38
|
+
},
|
|
39
|
+
"repository": {
|
|
40
|
+
"type": "git",
|
|
41
|
+
"url": "git+https://github.com/felixzsh/botforje.git"
|
|
42
|
+
},
|
|
43
|
+
"bugs": {
|
|
44
|
+
"url": "https://github.com/felixzsh/botforje/issues"
|
|
45
|
+
},
|
|
46
|
+
"homepage": "https://github.com/felixzsh/botforje#readme",
|
|
47
|
+
"license": "MIT",
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@types/inquirer": "^9.0.7",
|
|
50
|
+
"@types/jest": "^30.0.0",
|
|
51
|
+
"@types/js-yaml": "^4.0.9",
|
|
52
|
+
"@types/node": "^24.6.1",
|
|
53
|
+
"@types/qrcode-terminal": "^0.12.2",
|
|
54
|
+
"jest": "^30.2.0",
|
|
55
|
+
"ts-jest": "^29.4.4",
|
|
56
|
+
"ts-node": "^10.9.2",
|
|
57
|
+
"typescript": "^5.9.3"
|
|
58
|
+
},
|
|
59
|
+
"dependencies": {
|
|
60
|
+
"@types/express": "^5.0.3",
|
|
61
|
+
"commander": "^12.1.0",
|
|
62
|
+
"express": "^5.1.0",
|
|
63
|
+
"fuse.js": "^7.4.2",
|
|
64
|
+
"js-yaml": "^4.1.0",
|
|
65
|
+
"pino": "^10.0.0",
|
|
66
|
+
"pino-pretty": "^13.1.2",
|
|
67
|
+
"qrcode-terminal": "^0.12.0",
|
|
68
|
+
"whatsapp-web.js": "^1.34.7",
|
|
69
|
+
"botforje": "link:"
|
|
70
|
+
},
|
|
71
|
+
"engines": {
|
|
72
|
+
"node": ">=22.13.0"
|
|
73
|
+
},
|
|
74
|
+
"bin": {
|
|
75
|
+
"botforje": "dist/cli.js"
|
|
76
|
+
},
|
|
77
|
+
"files": [
|
|
78
|
+
"dist",
|
|
79
|
+
"scripts",
|
|
80
|
+
"service",
|
|
81
|
+
"README.md",
|
|
82
|
+
"LICENSE"
|
|
83
|
+
],
|
|
84
|
+
"os": [
|
|
85
|
+
"linux"
|
|
86
|
+
],
|
|
87
|
+
"scripts": {
|
|
88
|
+
"build": "tsc",
|
|
89
|
+
"dev": "ts-node src/cli.ts",
|
|
90
|
+
"start": "node ./dist/cli.js",
|
|
91
|
+
"test": "jest",
|
|
92
|
+
"test:watch": "jest --watch",
|
|
93
|
+
"test:coverage": "jest --coverage",
|
|
94
|
+
"postinstall": "node scripts/postinstall.js",
|
|
95
|
+
"preuninstall": "node scripts/preuninstall.js"
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { execSync } = require('child_process');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const os = require('os');
|
|
6
|
+
|
|
7
|
+
console.log('\nSetting up Botforje...\n');
|
|
8
|
+
|
|
9
|
+
function hasSystemd() {
|
|
10
|
+
if (os.platform() !== 'linux') return false;
|
|
11
|
+
try {
|
|
12
|
+
execSync('systemctl --version', { stdio: 'ignore' });
|
|
13
|
+
return true;
|
|
14
|
+
} catch {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (hasSystemd()) {
|
|
20
|
+
try {
|
|
21
|
+
console.log('Detected Linux system with systemd');
|
|
22
|
+
console.log('Configuring systemd service automatically...\n');
|
|
23
|
+
|
|
24
|
+
const setupScript = path.join(__dirname, 'setup-systemd.js');
|
|
25
|
+
execSync(`node "${setupScript}"`, { stdio: 'inherit' });
|
|
26
|
+
|
|
27
|
+
console.log('Installation complete!\n');
|
|
28
|
+
console.log('Quick Start:\n');
|
|
29
|
+
console.log(' 1. Start service: systemctl --user start botforje');
|
|
30
|
+
console.log(' 2. Enable on boot: systemctl --user enable botforje');
|
|
31
|
+
console.log(' 3. Check status: botforje status');
|
|
32
|
+
console.log(' 4. Authenticate: botforje auth <botId>');
|
|
33
|
+
console.log(' 5. View logs: journalctl --user -u botforje -f\n');
|
|
34
|
+
|
|
35
|
+
} catch (error) {
|
|
36
|
+
console.error('Automatic setup failed:', error.message);
|
|
37
|
+
console.log('\nYou can set it up manually: botforje setup\n');
|
|
38
|
+
process.exit(0);
|
|
39
|
+
}
|
|
40
|
+
} else {
|
|
41
|
+
console.log('Systemd not detected (macOS/Windows/Container)');
|
|
42
|
+
console.log('\nTo use Botforje:\n');
|
|
43
|
+
console.log('\n 1. Start daemon: botforje daemon');
|
|
44
|
+
console.log(' 2. Authenticate: botforje auth <botId>\n');
|
|
45
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const { execSync } = require('child_process');
|
|
6
|
+
const os = require('os');
|
|
7
|
+
|
|
8
|
+
function uninstallService() {
|
|
9
|
+
if (os.platform() !== 'linux') return;
|
|
10
|
+
|
|
11
|
+
try {
|
|
12
|
+
const homeDir = os.homedir();
|
|
13
|
+
const servicePath = path.join(homeDir, '.config', 'systemd', 'user', 'botforje.service');
|
|
14
|
+
const configDir = path.join(homeDir, '.config', 'botforje');
|
|
15
|
+
|
|
16
|
+
if (!fs.existsSync(servicePath)) return;
|
|
17
|
+
|
|
18
|
+
console.log('\nUninstalling Botforje service...\n');
|
|
19
|
+
|
|
20
|
+
// Stop service first to prevent hanging
|
|
21
|
+
console.log('Stopping service...');
|
|
22
|
+
try {
|
|
23
|
+
execSync('systemctl --user stop botforje 2>/dev/null', { stdio: 'inherit', timeout: 10000 });
|
|
24
|
+
} catch (error) {
|
|
25
|
+
console.log('Service may not be running or failed to stop gracefully');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Disable service
|
|
29
|
+
try {
|
|
30
|
+
execSync('systemctl --user disable botforje 2>/dev/null', { stdio: 'ignore' });
|
|
31
|
+
} catch {}
|
|
32
|
+
|
|
33
|
+
// Eliminar archivo .service
|
|
34
|
+
fs.unlinkSync(servicePath);
|
|
35
|
+
console.log('Service removed');
|
|
36
|
+
|
|
37
|
+
// Recargar systemd
|
|
38
|
+
execSync('systemctl --user daemon-reload', { stdio: 'ignore' });
|
|
39
|
+
|
|
40
|
+
console.log(`\nConfiguration kept at: ${configDir}`);
|
|
41
|
+
console.log(` To remove: rm -rf ${configDir}\n`);
|
|
42
|
+
|
|
43
|
+
} catch (error) {
|
|
44
|
+
console.error('Cleanup warning:', error.message);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
uninstallService();
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const { execSync } = require('child_process');
|
|
6
|
+
const os = require('os');
|
|
7
|
+
|
|
8
|
+
function setupSystemd() {
|
|
9
|
+
try {
|
|
10
|
+
if (os.platform() !== 'linux') {
|
|
11
|
+
console.log('Systemd setup is only available on Linux');
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const user = os.userInfo().username;
|
|
16
|
+
const homeDir = os.homedir();
|
|
17
|
+
const configDir = path.join(homeDir, '.config', 'botforje');
|
|
18
|
+
const systemdUserDir = path.join(homeDir, '.config', 'systemd', 'user');
|
|
19
|
+
|
|
20
|
+
const globalNpmRoot = execSync('npm root -g', { encoding: 'utf8' }).trim();
|
|
21
|
+
const scriptDir = path.dirname(__filename);
|
|
22
|
+
const projectRoot = path.resolve(scriptDir, '..');
|
|
23
|
+
|
|
24
|
+
// Detect mode: If project root is within global npm root, it's production
|
|
25
|
+
const isProduction = projectRoot.startsWith(globalNpmRoot);
|
|
26
|
+
const installDir = isProduction
|
|
27
|
+
? path.join(globalNpmRoot, 'botforje')
|
|
28
|
+
: projectRoot;
|
|
29
|
+
|
|
30
|
+
// For Node path, use 'which node' in both cases, but log a warning for dev
|
|
31
|
+
const nodePath = execSync('which node', { encoding: 'utf8' }).trim();
|
|
32
|
+
if (!isProduction) {
|
|
33
|
+
console.log('Development mode detected: Using local paths for testing');
|
|
34
|
+
console.log(` Install dir: ${installDir}`);
|
|
35
|
+
console.log(` Node path: ${nodePath}`);
|
|
36
|
+
console.log(' Note: Ensure dist/cli.js exists (run build first)');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
console.log('Setting up Botforje systemd service...');
|
|
40
|
+
|
|
41
|
+
if (!fs.existsSync(configDir)) {
|
|
42
|
+
fs.mkdirSync(configDir, { recursive: true });
|
|
43
|
+
console.log(`Created config directory: ${configDir}`);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Create example config file only if config.yml doesn't exist
|
|
47
|
+
const exampleConfigPath = path.join(__dirname, '..', 'config.example.yml');
|
|
48
|
+
const targetConfigPath = path.join(configDir, 'config.yml');
|
|
49
|
+
|
|
50
|
+
if (fs.existsSync(exampleConfigPath) && !fs.existsSync(targetConfigPath)) {
|
|
51
|
+
const exampleContent = fs.readFileSync(exampleConfigPath, 'utf8');
|
|
52
|
+
// Comment out all lines for the default config
|
|
53
|
+
const commentedContent = exampleContent
|
|
54
|
+
.split('\n')
|
|
55
|
+
.map(line => line.trim() ? `# ${line}` : line)
|
|
56
|
+
.join('\n');
|
|
57
|
+
fs.writeFileSync(targetConfigPath, commentedContent);
|
|
58
|
+
console.log(`Created example config file: ${targetConfigPath}`);
|
|
59
|
+
console.log(` Uncomment and edit this file to configure your bots`);
|
|
60
|
+
} else if (fs.existsSync(targetConfigPath)) {
|
|
61
|
+
console.log(`Config file already exists: ${targetConfigPath}`);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (!fs.existsSync(systemdUserDir)) {
|
|
65
|
+
fs.mkdirSync(systemdUserDir, { recursive: true });
|
|
66
|
+
console.log(`Created systemd user directory: ${systemdUserDir}`);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const templatePath = path.join(__dirname, '..', 'service', 'botforje.service.template');
|
|
70
|
+
let serviceContent = fs.readFileSync(templatePath, 'utf8');
|
|
71
|
+
|
|
72
|
+
serviceContent = serviceContent
|
|
73
|
+
.replace(/{{USER}}/g, user)
|
|
74
|
+
.replace(/{{INSTALL_DIR}}/g, installDir)
|
|
75
|
+
.replace(/{{NODE_PATH}}/g, nodePath)
|
|
76
|
+
.replace(/{{CONFIG_DIR}}/g, configDir);
|
|
77
|
+
|
|
78
|
+
const servicePath = path.join(systemdUserDir, 'botforje.service');
|
|
79
|
+
fs.writeFileSync(servicePath, serviceContent);
|
|
80
|
+
console.log(`Created service file: ${servicePath}`);
|
|
81
|
+
|
|
82
|
+
execSync('systemctl --user daemon-reload', { stdio: 'inherit' });
|
|
83
|
+
console.log('Reloaded systemd daemon\n');
|
|
84
|
+
|
|
85
|
+
} catch (error) {
|
|
86
|
+
console.error('Error setting up systemd service:', error.message);
|
|
87
|
+
throw error;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
setupSystemd();
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
[Unit]
|
|
2
|
+
Description=Botforje - WhatsApp Bot Service
|
|
3
|
+
After=network.target
|
|
4
|
+
Documentation=https://github.com/felixzsh/botforje
|
|
5
|
+
|
|
6
|
+
[Service]
|
|
7
|
+
Type=simple
|
|
8
|
+
WorkingDirectory={{INSTALL_DIR}}
|
|
9
|
+
ExecStart=xvfb-run -a {{NODE_PATH}} {{INSTALL_DIR}}/dist/cli.js daemon
|
|
10
|
+
Restart=on-failure
|
|
11
|
+
RestartSec=10
|
|
12
|
+
StandardOutput=journal
|
|
13
|
+
StandardError=journal
|
|
14
|
+
SyslogIdentifier=botforje
|
|
15
|
+
|
|
16
|
+
# Variables de entorno
|
|
17
|
+
Environment="NODE_ENV=production"
|
|
18
|
+
Environment="CONFIG_DIR={{CONFIG_DIR}}"
|
|
19
|
+
|
|
20
|
+
# Límites de seguridad
|
|
21
|
+
LimitNOFILE=65536
|
|
22
|
+
PrivateTmp=true
|
|
23
|
+
|
|
24
|
+
[Install]
|
|
25
|
+
WantedBy=multi-user.target
|