選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 

329 行
9.2 KiB

  1. require("dotenv").config();
  2. const { DisconnectReason } = require("@whiskeysockets/baileys");
  3. const makeWASocket = require("@whiskeysockets/baileys").default;
  4. const express = require("express");
  5. const app = express();
  6. const { Server } = require("socket.io");
  7. const http = require("http");
  8. const cors = require("cors");
  9. const qrCode = require("qrcode");
  10. const mongoConnection = require("./db/dbConnect");
  11. const cookieParser = require("cookie-parser");
  12. const bcrypt = require("bcryptjs");
  13. const User = require("./models/user");
  14. const path = require("path");
  15. const { signAccessToken, verifyAccessToken } = require("./helper/jwt_helper");
  16. const {
  17. createSignUpValidation,
  18. createSignInValidation,
  19. } = require("./validation/user.validity");
  20. const MyError = require("./config/error");
  21. const useMongoDBAuthState = require("./auth/mongoAuthState");
  22. const { MongoClient } = require("mongodb");
  23. mongoConnection();
  24. app.use(cookieParser());
  25. app.use(express.urlencoded({ extended: false }));
  26. app.use(express.json());
  27. app.use(express.static(path.join(__dirname, "client", "dist")));
  28. const server = http.createServer(app);
  29. const io = new Server(server, {
  30. cors: "http://localhost:3000",
  31. });
  32. const mongoClient = new MongoClient(process.env.mongodb_url, {
  33. useNewUrlParser: true,
  34. useUnifiedTopology: true,
  35. });
  36. mongoClient.connect().then(() => console.log("mongoClient connected"));
  37. const sock = {};
  38. // Function to set a global variable for a specific ID
  39. function setSock(id, value) {
  40. sock[id] = value;
  41. }
  42. let groupMessageEventListener;
  43. let connectionUpdateListener;
  44. async function generateQRCode(data) {
  45. return new Promise((resolve, reject) => {
  46. qrCode.toDataURL(data, (err, url) => {
  47. if (err) {
  48. reject(err);
  49. } else {
  50. resolve(url);
  51. }
  52. });
  53. });
  54. }
  55. async function connectionLogic(id, socket, isError) {
  56. // const { state, saveCreds } = await useMultiFileAuthState("auth_info_baileys");
  57. const user = await User.findById(id);
  58. console.log(user);
  59. const collection = mongoClient
  60. .db("whatsapp_api")
  61. .collection(`auth_info_${id}`);
  62. const chatsCollection = mongoClient
  63. .db("whatsapp_chats")
  64. .collection(`all_chats_${id}`);
  65. const { state, saveCreds } = await useMongoDBAuthState(collection);
  66. try {
  67. if (isError || user.isLogged === false) {
  68. let sock = makeWASocket({
  69. printQRInTerminal: true,
  70. auth: state,
  71. });
  72. setSock(id, sock);
  73. } else {
  74. sock[id].ev.off("messages.upsert", groupMessageEventListener);
  75. sock[id].ev.off("connection.update", connectionUpdateListener);
  76. }
  77. } catch (error) {
  78. console.error(error);
  79. }
  80. connectionUpdateListener = async (update) => {
  81. const { connection, lastDisconnect } = update;
  82. if (!connection && update?.qr) {
  83. const qrCodeDataURL = await generateQRCode(update.qr);
  84. console.log("QR created");
  85. socket.emit("qrCode", qrCodeDataURL);
  86. }
  87. if (connection === "close") {
  88. const shouldReconnect =
  89. lastDisconnect?.error?.output?.statusCode !==
  90. DisconnectReason.loggedOut;
  91. console.log(
  92. "connection closed due to ",
  93. lastDisconnect.error,
  94. ", reconnecting ",
  95. shouldReconnect
  96. );
  97. if (
  98. lastDisconnect.error?.output?.statusCode === DisconnectReason.loggedOut
  99. ) {
  100. console.log("User logged out Rereun the connection");
  101. // Handle user logout, perform cleanup, or redirect as needed
  102. await mongoClient.db("whatsapp_api").dropCollection(`auth_info_${id}`);
  103. user.isLogged = false;
  104. await user.save();
  105. socket.emit("user disconnected");
  106. }
  107. // if (lastDisconnect.error?.output?.statusCode === 440) {
  108. // await mongoClient.db("whatsapp_api").dropCollection(`auth_info_${id}`);
  109. // connectionLogic(id, socket);
  110. // }
  111. if (shouldReconnect) {
  112. connectionLogic(id, socket, true);
  113. }
  114. } else if (connection === "open") {
  115. console.log("opened connection");
  116. user.isLogged = true;
  117. await user.save();
  118. socket.emit("user connected");
  119. }
  120. };
  121. groupMessageEventListener = async (messageInfoUpsert) => {
  122. if (
  123. messageInfoUpsert.messages[0].key.remoteJid.split("@")[1] === "g.us" &&
  124. messageInfoUpsert.messages[0].message?.conversation
  125. ) {
  126. const user = await User.findById(id);
  127. const tags = user.tags;
  128. const newMessage = messageInfoUpsert.messages[0].message?.conversation;
  129. const isRequiredMessage =
  130. tags.length === 0
  131. ? true
  132. : tags.reduce((accum, curr) => {
  133. if (accum) return accum;
  134. else {
  135. const regex = new RegExp(curr, "i");
  136. console.log(accum, curr, newMessage);
  137. console.log(regex.test(newMessage));
  138. return regex.test(newMessage);
  139. }
  140. }, false);
  141. console.log(isRequiredMessage);
  142. const newGrpMessage = {
  143. conversation: messageInfoUpsert.messages[0].message?.conversation,
  144. username: messageInfoUpsert.messages[0].pushName,
  145. phoneNumber: messageInfoUpsert.messages[0].key.participant
  146. .split("@")[0]
  147. .slice(2),
  148. timestamp: new Date(
  149. messageInfoUpsert.messages[0].messageTimestamp * 1000
  150. ).toISOString(),
  151. };
  152. // console.log(messageInfoUpsert.messages[0]);
  153. if (isRequiredMessage) {
  154. socket.emit("new message", newGrpMessage);
  155. chatsCollection.insertOne(newGrpMessage);
  156. console.log(newGrpMessage);
  157. }
  158. }
  159. };
  160. sock[id].ev.on("connection.update", connectionUpdateListener);
  161. sock[id].ev.on("messages.upsert", groupMessageEventListener);
  162. sock[id].ev.on("creds.update", saveCreds);
  163. if (user.isLogged === true) {
  164. socket.emit("user connected");
  165. }
  166. }
  167. app.get("/", (req, res) => {
  168. res.status(200).json("Hey this is done");
  169. });
  170. app.post("/api/signup", async (req, res, next) => {
  171. try {
  172. await createSignUpValidation.validateAsync(req.body);
  173. const { username, password, email } = req.body;
  174. const hashedPassword = await bcrypt.hash(password, 10);
  175. const newUser = new User({ username, password: hashedPassword, email });
  176. await newUser.save();
  177. const token = await signAccessToken(newUser.id);
  178. const maxAgeInSeconds = 10 * 24 * 60 * 60;
  179. res.cookie("jwt", token, {
  180. httpOnly: true,
  181. maxAge: maxAgeInSeconds,
  182. });
  183. res.status(201).json(newUser);
  184. } catch (error) {
  185. next(error);
  186. }
  187. });
  188. app.get("/api/getMe", verifyAccessToken, async (req, res, next) => {
  189. try {
  190. const data = req.data;
  191. res.status(200).json(data);
  192. } catch (error) {
  193. next(error);
  194. }
  195. });
  196. app.post("/api/signin", async (req, res, next) => {
  197. try {
  198. await createSignInValidation.validateAsync(req.body);
  199. const { email, password } = req.body;
  200. console.log(email, password);
  201. const validUser = await User.checkUser(email, password);
  202. if (!validUser) throw new MyError("Invalid email or password");
  203. const token = await signAccessToken(validUser.id);
  204. const maxAgeInSeconds = 10 * 24 * 60 * 60;
  205. res.cookie("jwt", token, {
  206. httpOnly: true,
  207. maxAge: maxAgeInSeconds,
  208. });
  209. res.status(200).json(validUser);
  210. } catch (error) {
  211. next(error);
  212. }
  213. });
  214. app.get("/api/refreshMessages", verifyAccessToken, async (req, res, next) => {
  215. try {
  216. const data = req.data;
  217. const chatsCollection = mongoClient
  218. .db("whatsapp_chats")
  219. .collection(`all_chats_${data.id}`);
  220. console.log(sock);
  221. const messages = await chatsCollection
  222. .find({})
  223. .sort({ timestamp: -1 })
  224. .limit(20)
  225. .toArray();
  226. res.status(200).json(messages);
  227. } catch (error) {
  228. next(error);
  229. }
  230. });
  231. app.post("/api/tag/add", verifyAccessToken, async (req, res, next) => {
  232. try {
  233. const data = req.data;
  234. const { tag } = req.body;
  235. const userTag = await User.findByIdAndUpdate(
  236. data.id,
  237. { $addToSet: { tags: tag } },
  238. { new: true }
  239. );
  240. if (userTag) {
  241. return res.status(201).json(userTag);
  242. } else {
  243. return res.status(404).json("User not found");
  244. }
  245. } catch (error) {
  246. next(error);
  247. }
  248. });
  249. app.post("/api/tag/del", verifyAccessToken, async (req, res, next) => {
  250. try {
  251. const data = req.data;
  252. const { tag: deleteTag } = req.body;
  253. let user = await User.findById(data.id);
  254. let tags = user.tags;
  255. tags = tags.filter((tag) => tag !== deleteTag);
  256. user.tags = tags;
  257. await user.save();
  258. res.status(200).json(user);
  259. } catch (error) {
  260. next(error);
  261. }
  262. });
  263. // app.get("/createServer", verifyAccessToken, (req, res) => {
  264. // const data = req.data;
  265. // connectionLogic(data.id);
  266. // res.status(200).json("Server created");
  267. // });
  268. process.on("exit", async () => {
  269. User.updateMany({}, { isLogged: false });
  270. });
  271. io.on("connection", (socket) => {
  272. console.log("a user connected");
  273. socket.on("whatsapp connect", (id) => {
  274. connectionLogic(id, socket, false);
  275. });
  276. });
  277. app.get("*", (req, res) => {
  278. res.sendFile(path.join(__dirname, "client", "dist", "index.html"));
  279. });
  280. app.use((err, req, res, next) => {
  281. res.status(err.status || 500);
  282. res.json({
  283. status: err.status || 500,
  284. message: err.message || "Internal Server error",
  285. });
  286. });
  287. server.listen(3000, () => {
  288. console.log("listening on *:3000");
  289. });