-
Notifications
You must be signed in to change notification settings - Fork 142
Expand file tree
/
Copy pathqr.js
More file actions
270 lines (235 loc) Β· 12 KB
/
qr.js
File metadata and controls
270 lines (235 loc) Β· 12 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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
import express from 'express';
import fs from 'fs';
import pino from 'pino';
import { makeWASocket, useMultiFileAuthState, makeCacheableSignalKeyStore, Browsers, jidNormalizedUser, fetchLatestBaileysVersion } from '@whiskeysockets/baileys';
import { delay } from '@whiskeysockets/baileys';
import QRCode from 'qrcode';
import qrcodeTerminal from 'qrcode-terminal';
const router = express.Router();
// Function to remove files or directories
function removeFile(FilePath) {
try {
if (!fs.existsSync(FilePath)) return false;
fs.rmSync(FilePath, { recursive: true, force: true });
return true;
} catch (e) {
console.error('Error removing file:', e);
return false;
}
}
router.get('/', async (req, res) => {
// Generate unique session for each request to avoid conflicts
const sessionId = Date.now().toString() + Math.random().toString(36).substr(2, 9);
const dirs = `./qr_sessions/session_${sessionId}`;
// Ensure qr_sessions directory exists
if (!fs.existsSync('./qr_sessions')) {
fs.mkdirSync('./qr_sessions', { recursive: true });
}
async function initiateSession() {
// β
PERMANENT FIX: Create the session folder before anything
if (!fs.existsSync(dirs)) fs.mkdirSync(dirs, { recursive: true });
const { state, saveCreds } = await useMultiFileAuthState(dirs);
try {
const { version, isLatest } = await fetchLatestBaileysVersion();
let qrGenerated = false;
let responseSent = false;
// QR Code handling logic
const handleQRCode = async (qr) => {
if (qrGenerated || responseSent) return;
qrGenerated = true;
console.log('π’ QR Code Generated! Scan it with your WhatsApp app.');
console.log('π Instructions:');
console.log('1. Open WhatsApp on your phone');
console.log('2. Go to Settings > Linked Devices');
console.log('3. Tap "Link a Device"');
console.log('4. Scan the QR code below');
// Display QR in terminal
//qrcodeTerminal.generate(qr, { small: true });
try {
// Generate QR code as data URL
const qrDataURL = await QRCode.toDataURL(qr, {
errorCorrectionLevel: 'M',
type: 'image/png',
quality: 0.92,
margin: 1,
color: {
dark: '#000000',
light: '#FFFFFF'
}
});
if (!responseSent) {
responseSent = true;
console.log('QR Code generated successfully');
await res.send({
qr: qrDataURL,
message: 'QR Code Generated! Scan it with your WhatsApp app.',
instructions: [
'1. Open WhatsApp on your phone',
'2. Go to Settings > Linked Devices',
'3. Tap "Link a Device"',
'4. Scan the QR code above'
]
});
}
} catch (qrError) {
console.error('Error generating QR code:', qrError);
if (!responseSent) {
responseSent = true;
res.status(500).send({ code: 'Failed to generate QR code' });
}
}
};
// Improved Baileys socket configuration
const socketConfig = {
version,
logger: pino({ level: 'silent' }),
browser: Browsers.windows('Chrome'), // Using Browsers enum for better compatibility
auth: {
creds: state.creds,
keys: makeCacheableSignalKeyStore(state.keys, pino({ level: "fatal" }).child({ level: "fatal" })),
},
markOnlineOnConnect: false, // Disable to reduce connection issues
generateHighQualityLinkPreview: false, // Disable to reduce connection issues
defaultQueryTimeoutMs: 60000, // Increase timeout
connectTimeoutMs: 60000, // Increase connection timeout
keepAliveIntervalMs: 30000, // Keep connection alive
retryRequestDelayMs: 250, // Retry delay
maxRetries: 5, // Maximum retries
};
// Create socket and bind events
let sock = makeWASocket(socketConfig);
let reconnectAttempts = 0;
const maxReconnectAttempts = 3;
// Connection event handler function
const handleConnectionUpdate = async (update) => {
const { connection, lastDisconnect, qr } = update;
console.log(`π Connection update: ${connection || 'undefined'}`);
if (qr && !qrGenerated) {
await handleQRCode(qr);
}
if (connection === 'open') {
console.log('β
Connected successfully!');
console.log('πΎ Session saved to:', dirs);
reconnectAttempts = 0; // Reset reconnect attempts on successful connection
try {
// Read the session file
const sessionKnight = fs.readFileSync(dirs + '/creds.json');
// Get the user's JID from the session
const userJid = Object.keys(sock.authState.creds.me || {}).length > 0
? jidNormalizedUser(sock.authState.creds.me.id)
: null;
if (userJid) {
// Send session file to user
await sock.sendMessage(userJid, {
document: sessionKnight,
mimetype: 'application/json',
fileName: 'creds.json'
});
console.log("π Session file sent successfully to", userJid);
// Send video thumbnail with caption
await sock.sendMessage(userJid, {
image: { url: 'https://img.youtube.com/vi/-oz_u1iMgf8/maxresdefault.jpg' },
caption: `π¬ *KnightBot MD V2.0 Full Setup Guide!*\n\nπ Bug Fixes + New Commands + Fast AI Chat\nπΊ Watch Now: https://youtu.be/NjOipI2AoMk`
});
console.log("π¬ Video guide sent successfully");
// Send warning message
await sock.sendMessage(userJid, {
text: `β οΈDo not share this file with anybodyβ οΈ\n
ββ€β Thanks for using Knight Bot
βββββββββββββββ β³Ή
βΒ©2025 Mr Unique Hacker
βββββββββββββββββββ β³Ή\n\n`
});
} else {
console.log("β Could not determine user JID to send session file");
}
} catch (error) {
console.error("Error sending session file:", error);
}
// Clean up session after successful connection and sending files
setTimeout(() => {
console.log('π§Ή Cleaning up session...');
const deleted = removeFile(dirs);
if (deleted) {
console.log('β
Session cleaned up successfully');
} else {
console.log('β Failed to clean up session folder');
}
}, 15000); // Wait 15 seconds before cleanup to ensure messages are sent
}
if (connection === 'close') {
console.log('β Connection closed');
if (lastDisconnect?.error) {
console.log('β Last Disconnect Error:', lastDisconnect.error);
}
const statusCode = lastDisconnect?.error?.output?.statusCode;
// Handle specific error codes
if (statusCode === 401) {
console.log('π Logged out - need new QR code');
removeFile(dirs);
} else if (statusCode === 515 || statusCode === 503) {
console.log(`π Stream error (${statusCode}) - attempting to reconnect...`);
reconnectAttempts++;
if (reconnectAttempts <= maxReconnectAttempts) {
console.log(`π Reconnect attempt ${reconnectAttempts}/${maxReconnectAttempts}`);
// Wait a bit before reconnecting
setTimeout(() => {
try {
sock = makeWASocket(socketConfig);
sock.ev.on('connection.update', handleConnectionUpdate);
sock.ev.on('creds.update', saveCreds);
} catch (err) {
console.error('Failed to reconnect:', err);
}
}, 2000);
} else {
console.log('β Max reconnect attempts reached');
if (!responseSent) {
responseSent = true;
res.status(503).send({ code: 'Connection failed after multiple attempts' });
}
}
} else {
console.log('π Connection lost - attempting to reconnect...');
// Let it reconnect automatically
}
}
};
// Bind the event handler
sock.ev.on('connection.update', handleConnectionUpdate);
sock.ev.on('creds.update', saveCreds);
// Set a timeout to clean up if no QR is generated
setTimeout(() => {
if (!responseSent) {
responseSent = true;
res.status(408).send({ code: 'QR generation timeout' });
removeFile(dirs);
}
}, 30000); // 30 second timeout
} catch (err) {
console.error('Error initializing session:', err);
if (!res.headersSent) {
res.status(503).send({ code: 'Service Unavailable' });
}
removeFile(dirs);
}
}
await initiateSession();
});
// Global uncaught exception handler
process.on('uncaughtException', (err) => {
let e = String(err);
if (e.includes("conflict")) return;
if (e.includes("not-authorized")) return;
if (e.includes("Socket connection timeout")) return;
if (e.includes("rate-overlimit")) return;
if (e.includes("Connection Closed")) return;
if (e.includes("Timed Out")) return;
if (e.includes("Value not found")) return;
if (e.includes("Stream Errored")) return;
if (e.includes("Stream Errored (restart required)")) return;
if (e.includes("statusCode: 515")) return;
if (e.includes("statusCode: 503")) return;
console.log('Caught exception: ', err);
});
export default router;