-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.js
More file actions
149 lines (126 loc) · 4.93 KB
/
Copy pathindex.js
File metadata and controls
149 lines (126 loc) · 4.93 KB
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
const fs = require('fs');
const { execSync, spawn } = require('child_process');
const { Client, LocalAuth } = require('whatsapp-web.js');
const qrcode = require('qrcode-terminal');
require('dotenv').config();
const pyenv = process.env.VIRTUAL_ENV;
// ── Persistent Python/Whisper process ────────────────────────────────────────
let whisperReady = false;
const whisperProc = spawn(`${pyenv}/bin/python`, ['transcribe.py'], {
env:{
...process.env,
}
});
whisperProc.stdout.once('data', (data) => {
if (data.toString().trim() === 'READY') {
whisperReady = true;
console.log('🧠 Whisper caricato in memoria e pronto!');
}
});
whisperProc.stderr.on('data', (d) => console.error('🐍 Python:', d.toString()));
whisperProc.on('close', (code) => console.error(`🐍 Python terminato con codice ${code}`));
function transcribeAudio(mp3File) {
return new Promise((resolve, reject) => {
const onData = (data) => {
const line = data.toString().trim();
if (line.startsWith('OK ')) {
whisperProc.stdout.off('data', onData);
resolve(line.slice(3));
} else if (line.startsWith('ERR ')) {
whisperProc.stdout.off('data', onData);
reject(new Error(line.slice(4)));
}
};
whisperProc.stdout.on('data', onData);
whisperProc.stdin.write(mp3File + '\n');
});
}
// ── WhatsApp client ───────────────────────────────────────────────────────────
const client = new Client({
authStrategy: new LocalAuth(),
puppeteer: {
headless: true,
executablePath: '/usr/bin/chromium',
args: ['--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage', '--disable-gpu']
}
});
client.on('qr', qr => {
console.log('--- NUOVO QR CODE ---');
qrcode.generate(qr, { small: true });
});
client.on('ready', () => {
console.log('✅ BOT PRONTO');
console.log(' - Vocale in arrivo → trascrizione automatica');
console.log(' - Rispondi a un vocale con "!t" → trascrizione on-demand');
});
client.on('message_create', async (msg) => {
// ON-DEMAND: rispondi a un vocale con "!t"
if (msg.body === '!t' && msg.hasQuotedMsg) {
const quoted = await msg.getQuotedMessage();
if (quoted.hasMedia && (quoted.type === 'audio' || quoted.type === 'ptt')) {
await transcribe(quoted);
} else {
console.log('❌ Il messaggio citato non è un audio.');
}
return;
}
});
async function getSenderName(msg) {
try {
// in gruppi prende il nome del contatto
const contact = await msg.getContact();
return contact.pushname || contact.name || contact.number || msg.from;
} catch {
return msg.from;
}
}
async function transcribe(audioMsg) {
let rawFile = null;
let mp3File = null;
try {
if (!whisperReady) {
console.log('⏳ Whisper ancora in caricamento, riprova tra qualche secondo...');
return;
}
const media = await audioMsg.downloadMedia();
if (!media || !media.data) {
console.error('❌ Impossibile scaricare l\'audio.');
return;
}
const mimeToExt = {
'audio/ogg': 'ogg',
'audio/mpeg': 'mp3',
'audio/mp4': 'mp4',
'audio/webm': 'webm',
'audio/wav': 'wav'
};
const baseMime = media.mimetype.split(';')[0].trim();
const ext = mimeToExt[baseMime] || 'ogg';
const timestamp = Date.now();
rawFile = `./audio_${timestamp}.${ext}`;
mp3File = `./audio_${timestamp}.mp3`;
fs.writeFileSync(rawFile, media.data, 'base64');
execSync(`ffmpeg -y -i "${rawFile}" -ar 16000 -ac 1 -c:a libmp3lame "${mp3File}"`, { stdio: 'pipe' });
const [text, senderName] = await Promise.all([
transcribeAudio(mp3File),
getSenderName(audioMsg)
]);
const time = new Date().toLocaleTimeString('it-IT');
// ✅ Output pulito, solo quando trascrivi
console.log(`\n┌─────────────────────────────────`);
console.log(`│ 👤 ${senderName}`);
console.log(`│ 🕐 ${time}`);
console.log(`│`);
console.log(`│ 📝 ${text}`);
console.log(`└─────────────────────────────────\n`);
} catch (err) {
console.error('❌ Errore:', err.message);
} finally {
for (const f of [rawFile, mp3File]) {
if (f && fs.existsSync(f)) {
try { fs.unlinkSync(f); } catch (_) {}
}
}
}
}
client.initialize();