Skip to content

Commit ab269b5

Browse files
committed
chore: change Pairing Number use inquirer prompt
1 parent 610ba63 commit ab269b5

File tree

3 files changed

+465
-67
lines changed

3 files changed

+465
-67
lines changed

index.js

Lines changed: 58 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import NodeCache from '@cacheable/node-cache';
1313
import fs from 'fs/promises';
1414
import pino from 'pino';
1515
import cfonts from 'cfonts';
16+
import inquirer from 'inquirer';
1617

1718
const storeLogger = pino({ level: 'fatal', stream: 'store' });
1819
const silentLogger = pino({ level: 'silent' });
@@ -28,13 +29,8 @@ const displayBanner = () => {
2829
space: true
2930
});
3031

31-
const terminalWidth = process.stdout.columns;
32-
const centered = output.string
33-
.split('\n')
34-
.map(line => ' '.repeat(Math.max(0, (terminalWidth - line.length) >> 1)) + line)
35-
.join('\n');
36-
37-
console.log(centered);
32+
const w = process.stdout.columns;
33+
console.log(output.string.split('\n').map(l => ' '.repeat(Math.max(0, (w - l.length) >> 1)) + l).join('\n'));
3834
};
3935

4036
displayBanner();
@@ -50,21 +46,20 @@ global.plugins = loader.plugins;
5046

5147
const msgRetryCounterCache = new NodeCache();
5248
const groupMetadataCache = new Map();
53-
const CACHE_TTL = 5 * 60 * 1000;
54-
49+
const CACHE_TTL = 300000;
50+
const MAX_RECONNECT = 5;
5551
const RECONNECT_STRATEGIES = Object.freeze({
56-
408: { action: 'restart', delay: 2000, message: 'Connection timed out' },
57-
503: { action: 'restart', delay: 3000, message: 'Service unavailable' },
58-
428: { action: 'restart', delay: 2000, message: 'Connection closed' },
59-
515: { action: 'restart', delay: 2000, message: 'Connection closed' },
60-
401: { action: 'reset', delay: 1000, message: 'Session logged out' },
61-
403: { action: 'reset', delay: 1000, message: 'Account banned' },
62-
405: { action: 'reset', delay: 1000, message: 'Session not logged in' }
52+
408: { action: 'restart', delay: 2000, msg: 'Connection timed out' },
53+
503: { action: 'restart', delay: 3000, msg: 'Service unavailable' },
54+
428: { action: 'restart', delay: 2000, msg: 'Connection closed' },
55+
515: { action: 'restart', delay: 2000, msg: 'Connection closed' },
56+
401: { action: 'reset', delay: 1000, msg: 'Session logged out' },
57+
403: { action: 'reset', delay: 1000, msg: 'Account banned' },
58+
405: { action: 'reset', delay: 1000, msg: 'Session not logged in' }
6359
});
6460

6561
let reconnectAttempts = 0;
66-
const MAX_RECONNECT_ATTEMPTS = 5;
67-
const EXPONENTIAL_BACKOFF = true;
62+
let handlerModule = null;
6863

6964
const resetSession = async () => {
7065
try {
@@ -75,12 +70,6 @@ const resetSession = async () => {
7570
}
7671
};
7772

78-
const calculateDelay = (baseDelay, attempt) => {
79-
return EXPONENTIAL_BACKOFF
80-
? baseDelay * Math.pow(2, attempt - 1)
81-
: baseDelay * attempt;
82-
};
83-
8473
const handleReconnect = async (statusCode) => {
8574
const strategy = RECONNECT_STRATEGIES[statusCode];
8675

@@ -89,19 +78,15 @@ const handleReconnect = async (statusCode) => {
8978
process.exit(1);
9079
}
9180

92-
reconnectAttempts++;
93-
94-
if (reconnectAttempts > MAX_RECONNECT_ATTEMPTS) {
81+
if (++reconnectAttempts > MAX_RECONNECT) {
9582
log.fatal('Max reconnection attempts reached. Exiting...');
9683
process.exit(1);
9784
}
9885

99-
const delay = calculateDelay(strategy.delay, reconnectAttempts);
100-
log.warn(`${strategy.message}. Reconnecting in ${delay}ms... (Attempt ${reconnectAttempts}/${MAX_RECONNECT_ATTEMPTS})`);
86+
const delay = strategy.delay * Math.pow(2, reconnectAttempts - 1);
87+
log.warn(`${strategy.msg}. Reconnecting in ${delay}ms... (${reconnectAttempts}/${MAX_RECONNECT})`);
10188

102-
if (strategy.action === 'reset') {
103-
await resetSession();
104-
}
89+
if (strategy.action === 'reset') await resetSession();
10590

10691
await new Promise(resolve => setTimeout(resolve, delay));
10792
return startWA();
@@ -111,9 +96,7 @@ const fetchGroupMetadata = async (conn, groupId) => {
11196
const cached = groupMetadataCache.get(groupId);
11297
const now = Date.now();
11398

114-
if (cached && (now - cached.timestamp) < CACHE_TTL) {
115-
return cached.data;
116-
}
99+
if (cached && (now - cached.timestamp) < CACHE_TTL) return cached.data;
117100

118101
try {
119102
const metadata = await conn.groupMetadata(groupId);
@@ -127,6 +110,31 @@ const fetchGroupMetadata = async (conn, groupId) => {
127110

128111
const isValidGroupId = (id) => id && id !== 'status@broadcast' && id.endsWith('@g.us');
129112

113+
const getPairingNumber = async () => {
114+
try {
115+
const { phoneNumber } = await inquirer.prompt([
116+
{
117+
type: 'input',
118+
name: 'phoneNumber',
119+
message: 'Masukkan nomor WhatsApp (format: 62882xxxxxxxx):',
120+
validate: (input) => {
121+
const cleaned = input.replace(/\D/g, '');
122+
if (!cleaned) return 'Nomor telepon tidak boleh kosong';
123+
if (!cleaned.startsWith('62')) return 'Nomor harus diawali dengan 62';
124+
if (cleaned.length < 10 || cleaned.length > 15) return 'Panjang nomor tidak valid (10-15 digit)';
125+
return true;
126+
},
127+
filter: (input) => input.replace(/\D/g, '')
128+
}
129+
]);
130+
131+
return phoneNumber;
132+
} catch (err) {
133+
log.error(err.isTtyError ? 'Terminal tidak mendukung prompt interaktif' : `Error: ${err.message}`);
134+
process.exit(1);
135+
}
136+
};
137+
130138
async function startWA() {
131139
const { state, saveCreds } = await useMultiFileAuthState('sessions');
132140
const { version, isLatest } = await fetchLatestBaileysVersion();
@@ -147,12 +155,8 @@ async function startWA() {
147155
defaultQueryTimeoutMs: 60000,
148156
emitOwnEvents: false,
149157
fireInitQueries: true,
150-
getMessage: async (key) => {
151-
return { conversation: '' };
152-
},
153-
patchMessageBeforeSending: (message) => {
154-
return message;
155-
},
158+
getMessage: async () => ({ conversation: '' }),
159+
patchMessageBeforeSending: (msg) => msg,
156160
countryCode: 'ID',
157161
maxMsgRetryCount: 3,
158162
retryRequestDelayMs: 3000,
@@ -165,9 +169,11 @@ async function startWA() {
165169
conn.chats ??= {};
166170

167171
if (!conn.authState.creds.registered) {
172+
const pairingNumber = await getPairingNumber();
173+
168174
setTimeout(async () => {
169175
try {
170-
const code = await conn.requestPairingCode(PAIRING_NUMBER);
176+
const code = await conn.requestPairingCode(pairingNumber);
171177
log.info(`Pairing Code: ${code}`);
172178
} catch (err) {
173179
log.error(`Failed to get pairing code: ${err.message}`);
@@ -199,25 +205,19 @@ async function startWA() {
199205

200206
conn.ev.on('group-participants.update', async ({ id }) => {
201207
if (!isValidGroupId(id)) return;
202-
203208
const metadata = await fetchGroupMetadata(conn, id);
204209
if (metadata) conn.chats[id] = metadata;
205210
});
206211

207212
conn.ev.on('groups.update', async (updates) => {
208213
const validGroups = updates.filter(({ id }) => isValidGroupId(id));
209-
210-
if (validGroups.length === 0) return;
214+
if (!validGroups.length) return;
211215

212-
const promises = validGroups.map(async ({ id }) => {
216+
await Promise.allSettled(validGroups.map(async ({ id }) => {
213217
const metadata = await fetchGroupMetadata(conn, id);
214218
if (metadata) conn.chats[id] = metadata;
215-
});
216-
217-
await Promise.allSettled(promises);
219+
}));
218220
});
219-
220-
let handlerModule = null;
221221

222222
conn.ev.on('messages.upsert', async ({ messages }) => {
223223
const msg = messages[0];
@@ -226,15 +226,11 @@ async function startWA() {
226226
try {
227227
const m = await serialize(conn, msg);
228228

229-
if (m.chat.endsWith('@broadcast') ||
230-
m.type === 'protocolMessage' ||
231-
m.isBot) return;
229+
if (m.chat.endsWith('@broadcast') || m.type === 'protocolMessage' || m.isBot) return;
232230

233231
if (m.message) printMessage(m, conn);
234232

235-
if (!handlerModule) {
236-
handlerModule = await import('./handler.js');
237-
}
233+
if (!handlerModule) handlerModule = await import('./handler.js');
238234

239235
await handlerModule.default(conn, m);
240236
} catch (err) {
@@ -256,18 +252,14 @@ process.on('uncaughtException', (err) => {
256252
});
257253

258254
process.on('unhandledRejection', (reason, promise) => {
259-
log.error(`Unhandled Rejection at: ${promise}`);
260-
log.error(`Reason: ${reason}`);
255+
log.error(`Unhandled Rejection at: ${promise}, Reason: ${reason}`);
261256
});
262257

263-
process.on('SIGINT', async () => {
258+
const cleanup = async () => {
264259
log.info('Shutting down gracefully...');
265260
groupMetadataCache.clear();
266261
process.exit(0);
267-
});
262+
};
268263

269-
process.on('SIGTERM', async () => {
270-
log.info('Shutting down gracefully...');
271-
groupMetadataCache.clear();
272-
process.exit(0);
273-
});
264+
process.on('SIGINT', cleanup);
265+
process.on('SIGTERM', cleanup);

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
"chokidar": "^4.0.3",
3939
"file-type": "^17.1.1",
4040
"fluent-ffmpeg": "^2.1.3",
41+
"inquirer": "^12.9.6",
4142
"node-webpmux": "^3.2.1"
4243
}
4344
}

0 commit comments

Comments
 (0)