whatsapp-group-summary 1.0.0 ā 1.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/README.md +5 -5
- package/install.js +179 -30
- package/package.json +8 -2
package/README.md
CHANGED
|
@@ -136,13 +136,13 @@
|
|
|
136
136
|
### Step 1: Install Skill
|
|
137
137
|
|
|
138
138
|
```bash
|
|
139
|
-
#
|
|
140
|
-
npx
|
|
139
|
+
# ā” npx (recommended)
|
|
140
|
+
npx whatsapp-group-summary
|
|
141
141
|
|
|
142
|
-
#
|
|
143
|
-
hermes skills install
|
|
142
|
+
# šÆ Via Hermes CLI
|
|
143
|
+
hermes skills install whatsapp-group-summary
|
|
144
144
|
|
|
145
|
-
#
|
|
145
|
+
# š¦ Manual git clone
|
|
146
146
|
git clone https://github.com/mocasus/whatsapp-group-summary.git ~/.hermes/skills/whatsapp-group-summary-bot
|
|
147
147
|
```
|
|
148
148
|
|
package/install.js
CHANGED
|
@@ -1,59 +1,208 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* WhatsApp Group Summary Bot ā Installer
|
|
3
|
+
* WhatsApp Group Summary Bot ā One-Command Installer
|
|
4
4
|
*
|
|
5
5
|
* Usage: npx whatsapp-group-summary
|
|
6
6
|
*
|
|
7
|
-
*
|
|
7
|
+
* Installs the skill, validates Hermes setup, and guides through configuration.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
const fs = require('fs');
|
|
11
11
|
const path = require('path');
|
|
12
|
+
const os = require('os');
|
|
12
13
|
const { execSync } = require('child_process');
|
|
13
14
|
|
|
15
|
+
// āā Config āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
14
16
|
const SKILL_NAME = 'whatsapp-group-summary-bot';
|
|
15
|
-
const HERMES_HOME = process.env.HERMES_HOME || path.join(
|
|
16
|
-
const
|
|
17
|
+
const HERMES_HOME = process.env.HERMES_HOME || path.join(os.homedir(), '.hermes');
|
|
18
|
+
const SKILLS_DIR = path.join(HERMES_HOME, 'skills');
|
|
19
|
+
const TARGET_DIR = path.join(SKILLS_DIR, SKILL_NAME);
|
|
20
|
+
const HERMES_SRC = path.join(HERMES_HOME, 'hermes-agent');
|
|
17
21
|
const REPO_URL = 'https://github.com/mocasus/whatsapp-group-summary.git';
|
|
22
|
+
const NPM_URL = 'https://www.npmjs.com/package/whatsapp-group-summary';
|
|
18
23
|
|
|
19
|
-
|
|
20
|
-
|
|
24
|
+
// Colors
|
|
25
|
+
const c = { r: '\x1b[0m', g: '\x1b[32m', y: '\x1b[33m', b: '\x1b[34m', m: '\x1b[35m', w: '\x1b[37m', dim: '\x1b[2m' };
|
|
26
|
+
const ok = s => `${c.g}ā
${s}${c.r}`;
|
|
27
|
+
const warn = s => `${c.y}ā ļø ${s}${c.r}`;
|
|
28
|
+
const info = s => `${c.b}ā¹ļø ${s}${c.r}`;
|
|
29
|
+
const title = s => `${c.m}${s}${c.r}`;
|
|
30
|
+
const cmd = s => `${c.dim} $ ${s}${c.r}`;
|
|
21
31
|
|
|
22
|
-
|
|
23
|
-
|
|
32
|
+
// āā Helpers āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
33
|
+
function run(cmd, opts = {}) {
|
|
24
34
|
try {
|
|
25
|
-
execSync(
|
|
26
|
-
|
|
35
|
+
return execSync(cmd, { stdio: opts.silent ? 'pipe' : 'inherit', ...opts });
|
|
36
|
+
} catch { return null; }
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function exists(p) { return fs.existsSync(p); }
|
|
40
|
+
|
|
41
|
+
// āā Banner āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
42
|
+
console.log('');
|
|
43
|
+
console.log(title('š¤ WhatsApp Group Summary Bot'));
|
|
44
|
+
console.log(title(' for Hermes Agent'));
|
|
45
|
+
console.log(c.dim + ` ${NPM_URL}` + c.r);
|
|
46
|
+
console.log('');
|
|
47
|
+
|
|
48
|
+
// āā Step 0: Check Hermes āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
49
|
+
console.log(info('Checking Hermes installation...'));
|
|
50
|
+
|
|
51
|
+
const hermesBin = run('which hermes', { silent: true });
|
|
52
|
+
if (!hermesBin) {
|
|
53
|
+
console.log(warn('Hermes CLI not found. Install it first:'));
|
|
54
|
+
console.log(cmd('curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash'));
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
console.log(ok(`Hermes found at ${hermesBin.toString().trim()}`));
|
|
58
|
+
|
|
59
|
+
// Check if WhatsApp gateway is configured
|
|
60
|
+
const hermesHomeExists = exists(HERMES_HOME);
|
|
61
|
+
if (!hermesHomeExists) {
|
|
62
|
+
console.log(warn(`Hermes home not found at ${HERMES_HOME}`));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// āā Step 1: Install Skill āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
66
|
+
console.log(`\n${info}Installing ${SKILL_NAME}...`);
|
|
67
|
+
|
|
68
|
+
fs.mkdirSync(SKILLS_DIR, { recursive: true });
|
|
69
|
+
|
|
70
|
+
if (exists(TARGET_DIR)) {
|
|
71
|
+
console.log(warn('Existing installation found. Updating...'));
|
|
72
|
+
try {
|
|
73
|
+
run(`git -C "${TARGET_DIR}" pull`, { silent: true });
|
|
74
|
+
console.log(ok('Updated to latest version'));
|
|
27
75
|
} catch {
|
|
28
|
-
console.log('
|
|
76
|
+
console.log(warn('Git pull failed. Reinstalling...'));
|
|
29
77
|
fs.rmSync(TARGET_DIR, { recursive: true, force: true });
|
|
30
78
|
}
|
|
31
79
|
}
|
|
32
80
|
|
|
33
|
-
if (!
|
|
34
|
-
console.log('š¦ Cloning skill...');
|
|
81
|
+
if (!exists(TARGET_DIR)) {
|
|
35
82
|
try {
|
|
36
|
-
|
|
37
|
-
console.log('
|
|
38
|
-
} catch
|
|
39
|
-
|
|
83
|
+
run(`git clone "${REPO_URL}" "${TARGET_DIR}"`, { silent: true });
|
|
84
|
+
console.log(ok('Cloned from GitHub'));
|
|
85
|
+
} catch {
|
|
86
|
+
// Fallback: copy from npm package
|
|
87
|
+
const srcDir = __dirname;
|
|
40
88
|
fs.mkdirSync(TARGET_DIR, { recursive: true });
|
|
41
|
-
const
|
|
42
|
-
const files = fs.readdirSync(sourceDir);
|
|
89
|
+
const files = fs.readdirSync(srcDir);
|
|
43
90
|
for (const file of files) {
|
|
44
|
-
if (
|
|
45
|
-
const src = path.join(
|
|
91
|
+
if (['node_modules', '.git', 'package.json', 'install.js'].includes(file)) continue;
|
|
92
|
+
const src = path.join(srcDir, file);
|
|
46
93
|
const dest = path.join(TARGET_DIR, file);
|
|
47
|
-
fs.
|
|
94
|
+
if (fs.statSync(src).isDirectory()) {
|
|
95
|
+
fs.cpSync(src, dest, { recursive: true });
|
|
96
|
+
} else {
|
|
97
|
+
fs.copyFileSync(src, dest);
|
|
98
|
+
}
|
|
48
99
|
}
|
|
49
|
-
console.log('
|
|
100
|
+
console.log(ok('Installed from package (offline mode)'));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Remove .git to keep it clean
|
|
105
|
+
const gitDir = path.join(TARGET_DIR, '.git');
|
|
106
|
+
if (exists(gitDir)) fs.rmSync(gitDir, { recursive: true, force: true });
|
|
107
|
+
|
|
108
|
+
console.log(ok(`Skill installed at ${TARGET_DIR}`));
|
|
109
|
+
|
|
110
|
+
// āā Step 2: Check Patches āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
111
|
+
console.log(`\n${info}Checking source patches...`);
|
|
112
|
+
|
|
113
|
+
const patches = {
|
|
114
|
+
bridge: {
|
|
115
|
+
file: path.join(HERMES_SRC, 'scripts', 'whatsapp-bridge', 'bridge.js'),
|
|
116
|
+
check: (content) => content.includes('!isGroup && WHATSAPP_DM_POLICY'),
|
|
117
|
+
desc: 'Bridge group allowlist bypass',
|
|
118
|
+
},
|
|
119
|
+
adapter: {
|
|
120
|
+
file: path.join(HERMES_SRC, 'gateway', 'platforms', 'whatsapp_common.py'),
|
|
121
|
+
check: (content) => content.includes('patched ā allowlist check skipped for groups'),
|
|
122
|
+
desc: 'Adapter group allowlist bypass',
|
|
123
|
+
},
|
|
124
|
+
recorder: {
|
|
125
|
+
file: path.join(HERMES_SRC, 'plugins', 'platforms', 'whatsapp', 'adapter.py'),
|
|
126
|
+
check: (content) => content.includes('_record_group_message_sync'),
|
|
127
|
+
desc: 'Silent group message recorder',
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
let patchesOk = 0;
|
|
132
|
+
let patchesMissing = 0;
|
|
133
|
+
|
|
134
|
+
for (const [key, patch] of Object.entries(patches)) {
|
|
135
|
+
if (!exists(patch.file)) {
|
|
136
|
+
console.log(` ${warn('?')} ${patch.desc}: file not found (${path.relative(HERMES_HOME, patch.file)})`);
|
|
137
|
+
continue;
|
|
50
138
|
}
|
|
139
|
+
const content = fs.readFileSync(patch.file, 'utf8');
|
|
140
|
+
if (patch.check(content)) {
|
|
141
|
+
patchesOk++;
|
|
142
|
+
console.log(` ${ok('ā')} ${patch.desc}`);
|
|
143
|
+
} else {
|
|
144
|
+
patchesMissing++;
|
|
145
|
+
console.log(` ${warn('ā')} ${patch.desc} ā NEEDS PATCH`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// āā Step 3: Check Env āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
150
|
+
console.log(`\n${info}Checking environment config...`);
|
|
151
|
+
const envFile = path.join(HERMES_HOME, '.env');
|
|
152
|
+
let mentionSet = false;
|
|
153
|
+
if (exists(envFile)) {
|
|
154
|
+
const envContent = fs.readFileSync(envFile, 'utf8');
|
|
155
|
+
mentionSet = /WHATSAPP_REQUIRE_MENTION\s*=\s*true/i.test(envContent);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (mentionSet) {
|
|
159
|
+
console.log(ok('WHATSAPP_REQUIRE_MENTION=true'));
|
|
160
|
+
} else {
|
|
161
|
+
console.log(warn('WHATSAPP_REQUIRE_MENTION=true not set'));
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// āā Summary & Next Steps āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
165
|
+
console.log(`\n${'ā'.repeat(50)}`);
|
|
166
|
+
console.log(title('š Next Steps'));
|
|
167
|
+
console.log(`${'ā'.repeat(50)}\n`);
|
|
168
|
+
|
|
169
|
+
const steps = [];
|
|
170
|
+
|
|
171
|
+
if (patchesMissing > 0) {
|
|
172
|
+
steps.push('1. Apply source patches:');
|
|
173
|
+
steps.push(' See README for detailed diff instructions');
|
|
174
|
+
steps.push(` ${cmd}cat ${path.join(TARGET_DIR, 'README.md')}`);
|
|
175
|
+
steps.push('');
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (!mentionSet) {
|
|
179
|
+
steps.push('2. Set environment variable:');
|
|
180
|
+
steps.push(' Add to Hermes env config:');
|
|
181
|
+
steps.push(` WHATSAPP_REQUIRE_MENTION=true`);
|
|
182
|
+
steps.push('');
|
|
51
183
|
}
|
|
52
184
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
185
|
+
steps.push(`${patchesMissing > 0 ? '3' : '1'}. Restart gateway:`);
|
|
186
|
+
steps.push(` ${cmd}hermes gateway restart`);
|
|
187
|
+
steps.push(' (Must run from separate SSH terminal)');
|
|
188
|
+
steps.push('');
|
|
189
|
+
steps.push(`${patchesMissing > 0 ? '4' : '2'}. Get group ID:`);
|
|
190
|
+
steps.push(' Tag @Hermes in your WhatsApp group: "apa id grup ini?"');
|
|
191
|
+
steps.push('');
|
|
192
|
+
steps.push(`${patchesMissing > 0 ? '5' : '3'}. Setup cron jobs:`);
|
|
193
|
+
steps.push(' Morning: 0 0 * * * (07:00 WIB)');
|
|
194
|
+
steps.push(' Evening: 0 16 * * * (23:00 WIB)');
|
|
195
|
+
steps.push(` Prompt: ${cmd}cat ${path.join(TARGET_DIR, 'SKILL.md')}`);
|
|
196
|
+
steps.push('');
|
|
197
|
+
|
|
198
|
+
for (const s of steps) console.log(` ${s}`);
|
|
199
|
+
|
|
200
|
+
console.log(title('š Full Guide'));
|
|
201
|
+
console.log(` ${c.dim}https://github.com/mocasus/whatsapp-group-summary${c.r}`);
|
|
202
|
+
console.log('');
|
|
203
|
+
|
|
204
|
+
if (patchesMissing > 0) {
|
|
205
|
+
console.log(warn(`${patchesMissing} patch(es) need to be applied before recording works.`));
|
|
206
|
+
} else {
|
|
207
|
+
console.log(ok('All patches detected! Recording should work after restart.'));
|
|
208
|
+
}
|
package/package.json
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "whatsapp-group-summary",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "WhatsApp group chat summary bot for Hermes Agent ā record all messages silently, auto-summarize 2x daily",
|
|
5
5
|
"main": "install.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"whatsapp-group-summary": "./install.js"
|
|
8
8
|
},
|
|
9
|
-
"keywords": [
|
|
9
|
+
"keywords": [
|
|
10
|
+
"hermes-agent",
|
|
11
|
+
"whatsapp",
|
|
12
|
+
"summary",
|
|
13
|
+
"group-chat",
|
|
14
|
+
"bot"
|
|
15
|
+
],
|
|
10
16
|
"author": "mocasus",
|
|
11
17
|
"license": "MIT",
|
|
12
18
|
"repository": {
|