Reaperxxxx commited on
Commit
a1f22c8
·
verified ·
1 Parent(s): a5a8afd

Create server.js

Browse files
Files changed (1) hide show
  1. server.js +289 -0
server.js ADDED
@@ -0,0 +1,289 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const fs = require("fs");
2
+ const express = require("express");
3
+ const { makeWASocket, fetchLatestBaileysVersion, useMultiFileAuthState, makeInMemoryStore } = require("@whiskeysockets/baileys");
4
+ const http = require("http");
5
+ const socketIo = require("socket.io");
6
+ const bodyParser = require("body-parser");
7
+ const path = require("path");
8
+
9
+ const app = express();
10
+ const server = http.createServer(app);
11
+ const io = socketIo(server);
12
+ const PORT = process.env.PORT || 7860;
13
+
14
+ const store = makeInMemoryStore({});
15
+
16
+ // Paths
17
+ const MESSAGES_FILE = "./messages.json";
18
+ const SESSION_DIR = "./session"; // Directory to store session credentials
19
+
20
+ // Initialize Express
21
+ // Middleware
22
+ app.use(express.static("public"));
23
+ app.use(bodyParser.json());
24
+
25
+ // Load or initialize `messages.json`
26
+ if (!fs.existsSync(MESSAGES_FILE)) fs.writeFileSync(MESSAGES_FILE, JSON.stringify([]));
27
+ const loadMessages = () => JSON.parse(fs.readFileSync(MESSAGES_FILE));
28
+ const saveMessages = (messages) => fs.writeFileSync(MESSAGES_FILE, JSON.stringify(messages));
29
+
30
+ // Initialize Baileys with saved session keys
31
+ const initBaileys = async () => {
32
+ const { version } = await fetchLatestBaileysVersion();
33
+ const { state, saveCreds } = await useMultiFileAuthState(SESSION_DIR);
34
+
35
+ const socket = makeWASocket({
36
+ auth: state,
37
+ version,
38
+ });
39
+
40
+ store.bind(socket.ev);
41
+
42
+ // Function to get the name for a chat
43
+ const getChatName = async (jid) => {
44
+ if (jid.endsWith("@g.us")) {
45
+ // Fetch group metadata for group chats
46
+ try {
47
+ const metadata = await whatsappSocket.groupMetadata(jid);
48
+ return metadata.subject || "Unknown Group";
49
+ } catch (err) {
50
+ console.error("Error fetching group metadata:", err);
51
+ return "Unknown Group";
52
+ }
53
+ } else {
54
+ // Use contact name for personal chats
55
+ const contact = store.contacts[jid]; // Fetch from store
56
+ return contact?.name || contact?.notify || jid; // Fallback to JID if name is not available
57
+ }
58
+ };
59
+
60
+ // Listen for new messages
61
+ socket.ev.on("messages.upsert", async ({ messages }) => {
62
+ const allMessages = loadMessages();
63
+
64
+ for (const msg of messages) {
65
+ if (msg.message) {
66
+ // Extract message content
67
+ let content = "[Unsupported Message Type]";
68
+
69
+ // Handle different message types
70
+ if (msg.message.conversation) {
71
+ content = msg.message.conversation;
72
+ } else if (msg.message.extendedTextMessage) {
73
+ content = msg.message.extendedTextMessage.text;
74
+ } else if (msg.message.imageMessage) {
75
+ content = msg.message.imageMessage.caption || "[Image]";
76
+ } else if (msg.message.videoMessage) {
77
+ content = msg.message.videoMessage.caption || "[Video]";
78
+ } else if (msg.message.stickerMessage) {
79
+ content = "[Sticker]";
80
+ } else if (msg.message.documentMessage) {
81
+ content = msg.message.documentMessage.fileName || "[Document]";
82
+ } else if (msg.message.audioMessage) {
83
+ content = "[Audio]";
84
+ } else if (msg.message.contactMessage) {
85
+ content = `[Contact: ${msg.message.contactMessage.displayName || "Unknown"}]`;
86
+ } else if (msg.message.locationMessage) {
87
+ const { degreesLatitude, degreesLongitude } = msg.message.locationMessage;
88
+ content = `[Location: ${degreesLatitude}, ${degreesLongitude}]`;
89
+ } else if (msg.message.buttonsMessage) {
90
+ content = msg.message.buttonsMessage.contentText || "[Buttons Message]";
91
+ } else if (msg.message.listMessage) {
92
+ content = msg.message.listMessage.description || "[List Message]";
93
+ } else if (msg.message.pollCreationMessage) {
94
+ content = msg.message.pollCreationMessage.name || "[Poll]";
95
+ }
96
+
97
+ // Fetch the chat name
98
+ const chatName = await getChatName(msg.key.remoteJid);
99
+
100
+ // Format the message data
101
+ const messageData = {
102
+ jid: msg.key.remoteJid,
103
+ sender: msg.key.fromMe ? "You" : msg.pushName || msg.key.remoteJid,
104
+ chatName,
105
+ content,
106
+ timestamp: msg.messageTimestamp,
107
+ };
108
+
109
+ // Save to messages.json
110
+ allMessages.push(messageData);
111
+ saveMessages(allMessages);
112
+
113
+ // Emit the message to the frontend via WebSocket
114
+ io.emit("new_message", messageData);
115
+ }
116
+ }
117
+ });
118
+
119
+ // Save credentials on update
120
+ socket.ev.on("connection.update", (update) => {
121
+ const { connection, lastDisconnect } = update;
122
+
123
+ if (connection === "open") {
124
+ console.log("WhatsApp connected!");
125
+ } else if (connection === "close") {
126
+ console.error("Connection closed:", lastDisconnect?.error);
127
+ }
128
+ });
129
+
130
+ // Save credentials on update
131
+ socket.ev.on("creds.update", saveCreds);
132
+
133
+ return socket;
134
+ };
135
+
136
+ // Initialize Baileys socket
137
+ let whatsappSocket;
138
+ initBaileys()
139
+ .then((sock) => {
140
+ whatsappSocket = sock;
141
+ console.log("Connected to WhatsApp");
142
+ })
143
+ .catch((err) => console.error("Failed to initialize Baileys:", err));
144
+
145
+ // Routes
146
+ app.get("/", (req, res) => {
147
+ res.sendFile(path.join(__dirname, "public", "index.html"));
148
+ });
149
+
150
+ app.get("/chat/:jid", (req, res) => {
151
+ res.sendFile(path.join(__dirname, "public", "chat.html"));
152
+ });
153
+
154
+ app.get("/api/messages", async (req, res) => {
155
+ const allMessages = loadMessages();
156
+ const uniqueChatsMap = new Map(); // To track unique chats with their data
157
+
158
+ for (const msg of allMessages) {
159
+ // Check if the chat is already processed
160
+ const existingChat = uniqueChatsMap.get(msg.jid);
161
+ if (existingChat) {
162
+ // Update the last message if the timestamp is newer
163
+ if (msg.timestamp > existingChat.timestamp) {
164
+ existingChat.lastMessage = msg.content;
165
+ existingChat.timestamp = msg.timestamp;
166
+ }
167
+ } else {
168
+ // Fetch chat name dynamically
169
+ try {
170
+ const chatName = await getChatName(msg.jid);
171
+ uniqueChatsMap.set(msg.jid, {
172
+ jid: msg.jid,
173
+ chatName,
174
+ lastMessage: msg.content,
175
+ timestamp: msg.timestamp,
176
+ });
177
+ } catch (error) {
178
+ console.error(`Failed to fetch chat name for ${msg.jid}:`, error);
179
+ }
180
+ }
181
+ }
182
+
183
+ // Convert Map to array and sort by timestamp
184
+ const uniqueChats = Array.from(uniqueChatsMap.values());
185
+ uniqueChats.sort((a, b) => b.timestamp - a.timestamp);
186
+
187
+ res.json(uniqueChats);
188
+ });
189
+
190
+ app.get("/messages.json", (req, res) => {
191
+ res.sendFile(path.join(__dirname, "messages.json"));
192
+ });
193
+
194
+ app.get("/api/messages/:jid", (req, res) => {
195
+ const { jid } = req.params;
196
+ const chatMessages = loadMessages().filter((msg) => msg.jid === jid);
197
+ res.json(chatMessages);
198
+ });
199
+
200
+ // WebSocket Connection
201
+ io.on("connection", (socket) => {
202
+ console.log("Client connected via WebSocket");
203
+ socket.on("disconnect", () => {
204
+ console.log("Client disconnected");
205
+ });
206
+ });
207
+
208
+ app.post("/send-message", async (req, res) => {
209
+ const { jid, message, replyTo } = req.body;
210
+ try {
211
+ if (whatsappSocket) {
212
+ if (replyTo) {
213
+ const messages = loadMessages();
214
+ const replyMessage = messages.find((msg) => msg.jid === jid && msg.timestamp === replyTo);
215
+
216
+ if (replyMessage) {
217
+ await whatsappSocket.sendMessage(jid, {
218
+ text: message,
219
+ quoted: {
220
+ key: { remoteJid: jid, id: replyTo },
221
+ message: { conversation: replyMessage.content },
222
+ },
223
+ });
224
+ }
225
+ } else {
226
+ await whatsappSocket.sendMessage(jid, { text: message });
227
+ }
228
+ res.sendStatus(200);
229
+ } else {
230
+ res.sendStatus(500);
231
+ }
232
+ } catch (error) {
233
+ console.error("Error sending message:", error);
234
+ res.sendStatus(500);
235
+ }
236
+ });
237
+
238
+ app.post("/send-sticker", async (req, res) => {
239
+ const { jid, stickerPath } = req.body;
240
+ try {
241
+ if (whatsappSocket && fs.existsSync(stickerPath)) {
242
+ await whatsappSocket.sendMessage(jid, { sticker: { url: stickerPath } });
243
+ res.sendStatus(200);
244
+ } else {
245
+ res.status(400).send("Sticker file not found or session not initialized.");
246
+ }
247
+ } catch (error) {
248
+ console.error("Error sending sticker:", error);
249
+ res.sendStatus(500);
250
+ }
251
+ });
252
+
253
+ app.post("/send-image", async (req, res) => {
254
+ const { jid, imagePath, caption } = req.body;
255
+ try {
256
+ if (whatsappSocket && fs.existsSync(imagePath)) {
257
+ await whatsappSocket.sendMessage(jid, {
258
+ image: { url: imagePath },
259
+ caption: caption || "",
260
+ });
261
+ res.sendStatus(200);
262
+ } else {
263
+ res.status(400).send("Image file not found or session not initialized.");
264
+ }
265
+ } catch (error) {
266
+ console.error("Error sending image:", error);
267
+ res.sendStatus(500);
268
+ }
269
+ });
270
+
271
+ // WebSocket connection
272
+ io.on('connection', (socket) => {
273
+ console.log('User connected');
274
+
275
+ // Example event to listen for new messages
276
+ socket.on('sendMessage', (message) => {
277
+ saveMessage(message); // Save the message to storage
278
+
279
+ // Broadcast to all connected clients
280
+ io.emit('newMessage', message);
281
+ });
282
+
283
+ socket.on('disconnect', () => {
284
+ console.log('User disconnected');
285
+ });
286
+ });
287
+
288
+ // Start server
289
+ server.listen(PORT, () => console.log(`Server running on http://localhost:${PORT}`));