diff --git a/package-lock.json b/package-lock.json index 2c9628a..5d69855 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,11 +13,11 @@ "dotenv": "^16.5.0", "express": "^4.21.2", "express-rate-limit": "^7.4.1", - "pino": "^9.6.0", + "pino": "^9.7.0", "qr-image": "^3.2.0", "qrcode-terminal": "^0.12.0", "swagger-ui-express": "^5.0.1", - "whatsapp-web.js": "^1.28.0", + "whatsapp-web.js": "^1.28.1-alpha.0", "ws": "^8.18.2" }, "devDependencies": { @@ -6362,9 +6362,9 @@ } }, "node_modules/pino": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/pino/-/pino-9.6.0.tgz", - "integrity": "sha512-i85pKRCt4qMjZ1+L7sy2Ag4t1atFcdbEt76+7iRJn1g2BvsnRMGu9p8pivl9fs63M2kF/A0OacFZhTub+m/qMg==", + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-9.7.0.tgz", + "integrity": "sha512-vnMCM6xZTb1WDmLvtG2lE/2p+t9hDEIvTWJsu6FejkE62vB7gDhvzrpFR4Cw2to+9JNQxVnkAKVPA1KPB98vWg==", "license": "MIT", "dependencies": { "atomic-sleep": "^1.0.0", @@ -6372,7 +6372,7 @@ "on-exit-leak-free": "^2.1.0", "pino-abstract-transport": "^2.0.0", "pino-std-serializers": "^7.0.0", - "process-warning": "^4.0.0", + "process-warning": "^5.0.0", "quick-format-unescaped": "^4.0.3", "real-require": "^0.2.0", "safe-stable-stringify": "^2.3.1", @@ -6533,9 +6533,19 @@ "optional": true }, "node_modules/process-warning": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-4.0.0.tgz", - "integrity": "sha512-/MyYDxttz7DfGMMHiysAsFE4qF+pQYAA8ziO/3NcRVrQ5fSk+Mns4QZA/oRPFzvcqNoVJXQNWNAsdwBXLUkQKw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-5.0.0.tgz", + "integrity": "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], "license": "MIT" }, "node_modules/progress": { @@ -8108,9 +8118,9 @@ "license": "BSD-2-Clause" }, "node_modules/whatsapp-web.js": { - "version": "1.28.0", - "resolved": "https://registry.npmjs.org/whatsapp-web.js/-/whatsapp-web.js-1.28.0.tgz", - "integrity": "sha512-rNIgtjjUzCFkOF2prypdkJv3tJw+vToOLjvmlRoMxyyEVlFzJvlvqpicbb5sE9ys4+vY10OzZRQscwC6rjo96w==", + "version": "1.28.1-alpha.0", + "resolved": "https://registry.npmjs.org/whatsapp-web.js/-/whatsapp-web.js-1.28.1-alpha.0.tgz", + "integrity": "sha512-vRmseUwlDcaRmTZ+9PVifnsEU6pRd7A6/ZjuIbzX6opOYYkNcfwXeO6AFuLrn+V7T+kiSeNweIUtiOtcuc9B0A==", "license": "Apache-2.0", "dependencies": { "@pedroslopez/moduleraid": "^5.0.2", diff --git a/package.json b/package.json index 0f038e6..ff86872 100644 --- a/package.json +++ b/package.json @@ -13,11 +13,11 @@ "dotenv": "^16.5.0", "express": "^4.21.2", "express-rate-limit": "^7.4.1", - "pino": "^9.6.0", + "pino": "^9.7.0", "qr-image": "^3.2.0", "qrcode-terminal": "^0.12.0", "swagger-ui-express": "^5.0.1", - "whatsapp-web.js": "^1.28.0", + "whatsapp-web.js": "^1.28.1-alpha.0", "ws": "^8.18.2" }, "devDependencies": { diff --git a/src/controllers/clientController.js b/src/controllers/clientController.js index c302c4b..54237ea 100644 --- a/src/controllers/clientController.js +++ b/src/controllers/clientController.js @@ -1708,6 +1708,110 @@ const openChatWindow = async (req, res) => { } } +/** + * Open or scroll the chat window to the position of the message. + * + * @async + * @function + * @param {Object} req - The HTTP request object containing the chatId and sessionId. + * @param {string} req.body.chatId - The unique identifier of the chat to unmute. + * @param {string} req.params.sessionId - The unique identifier of the session associated with the client to use. + * @param {Object} res - The HTTP response object. + * @returns {Promise} - A Promise that resolves with a JSON object containing a success flag and the result of the operation. + * @throws {Error} - If an error occurs during the operation, it is thrown and handled by the catch block. + */ +const openChatWindowAt = async (req, res) => { + /* + #swagger.summary = 'Open the chat window to the position of the message' + #swagger.requestBody = { + required: true, + schema: { + type: 'object', + properties: { + messageId: { + type: 'string', + description: 'ID of the message to scroll to (serialized)', + example: 'false_31235678901@c.us_3A40CB10BC3680B1EE' + }, + } + }, + } + */ + try { + const { messageId } = req.body + const client = sessions.get(req.params.sessionId) + await client.interface.openChatWindowAt(messageId) + res.json({ success: true }) + } catch (error) { + sendErrorResponse(res, 500, error.message) + } +} + +/** + * Force reset of connection state for the client. + * + * @async + * @function + * @param {Object} req - The HTTP request object containing the chatId and sessionId. + * @param {string} req.body.chatId - The unique identifier of the chat to unmute. + * @param {string} req.params.sessionId - The unique identifier of the session associated with the client to use. + * @param {Object} res - The HTTP response object. + * @returns {Promise} - A Promise that resolves with a JSON object containing a success flag and the result of the operation. + * @throws {Error} - If an error occurs during the operation, it is thrown and handled by the catch block. + */ +const resetState = async (req, res) => { + /* + #swagger.summary = 'Force reset of connection state for the client' + */ + try { + const client = sessions.get(req.params.sessionId) + await client.resetState() + res.json({ success: true }) + } catch (error) { + sendErrorResponse(res, 500, error.message) + } +} + +/** + * Change the background synchronization setting. + * + * @async + * @function + * @param {Object} req - The HTTP request object containing the chatId and sessionId. + * @param {string} req.body.chatId - The unique identifier of the chat to unmute. + * @param {string} req.params.sessionId - The unique identifier of the session associated with the client to use. + * @param {Object} res - The HTTP response object. + * @returns {Promise} - A Promise that resolves with a JSON object containing a success flag and the result of the operation. + * @throws {Error} - If an error occurs during the operation, it is thrown and handled by the catch block. + */ +const setBackgroundSync = async (req, res) => { + /* + #swagger.summary = 'Change the background synchronization setting' + #swagger.description = 'NOTE: This action will take effect after you restart the client' + #swagger.requestBody = { + required: true, + schema: { + type: 'object', + properties: { + flag: { + type: 'boolean', + description: 'flag true/false', + example: true + }, + } + }, + } + */ + try { + const { flag = true } = req.body + const client = sessions.get(req.params.sessionId) + await client.setBackgroundSync(flag) + res.json({ success: true }) + } catch (error) { + sendErrorResponse(res, 500, error.message) + } +} + module.exports = { getClassInfo, acceptInvite, @@ -1753,5 +1857,8 @@ module.exports = { getContactDeviceCount, getCountryCode, getFormattedNumber, - openChatWindow + openChatWindow, + openChatWindowAt, + resetState, + setBackgroundSync } diff --git a/src/controllers/messageController.js b/src/controllers/messageController.js index f422d61..cfb1f49 100644 --- a/src/controllers/messageController.js +++ b/src/controllers/messageController.js @@ -79,17 +79,22 @@ const deleteMessage = async (req, res) => { type: 'boolean', description: 'If true and the message is sent by the current user or the user is an admin, will delete it for everyone in the chat.', example: true + }, + clearMedia: { + type: 'boolean', + description: 'If true, any associated media will also be deleted from a device', + example: true } } } } */ try { - const { messageId, chatId, everyone } = req.body + const { messageId, chatId, everyone, clearMedia = true } = req.body const client = sessions.get(req.params.sessionId) const message = await _getMessageById(client, messageId, chatId) if (!message) { throw new Error('Message not found') } - const result = await message.delete(everyone) + const result = await message.delete(everyone, clearMedia) res.json({ success: true, result }) } catch (error) { sendErrorResponse(res, 500, error.message) diff --git a/src/routes.js b/src/routes.js index 496dbda..133edb1 100644 --- a/src/routes.js +++ b/src/routes.js @@ -104,6 +104,9 @@ clientRouter.post('/getContactDeviceCount/:sessionId', [middleware.sessionNameVa clientRouter.post('/getCountryCode/:sessionId', [middleware.sessionNameValidation, middleware.sessionValidation], clientController.getCountryCode) clientRouter.post('/getFormattedNumber/:sessionId', [middleware.sessionNameValidation, middleware.sessionValidation], clientController.getFormattedNumber) clientRouter.post('/openChatWindow/:sessionId', [middleware.sessionNameValidation, middleware.sessionValidation], clientController.openChatWindow) +clientRouter.post('/openChatWindowAt/:sessionId', [middleware.sessionNameValidation, middleware.sessionValidation], clientController.openChatWindowAt) +clientRouter.post('/resetState/:sessionId', [middleware.sessionNameValidation, middleware.sessionValidation], clientController.resetState) +clientRouter.post('/setBackgroundSync/:sessionId', [middleware.sessionNameValidation, middleware.sessionValidation], clientController.setBackgroundSync) /** * ================ diff --git a/swagger.json b/swagger.json index 9c17c28..f954a6f 100644 --- a/swagger.json +++ b/swagger.json @@ -3664,10 +3664,10 @@ "schema": { "type": "object", "properties": { - "chatId": { - "type": "string", - "description": "ID of the chat", - "example": "6281288888888@c.us" + "flag": { + "type": "boolean", + "description": "flag true/false", + "example": true } } } @@ -3676,10 +3676,10 @@ "schema": { "type": "object", "properties": { - "chatId": { - "type": "string", - "description": "ID of the chat", - "example": "6281288888888@c.us" + "flag": { + "type": "boolean", + "description": "flag true/false", + "example": true } } } @@ -5130,6 +5130,277 @@ } } }, + "/client/openChatWindowAt/{sessionId}": { + "post": { + "tags": [ + "Client" + ], + "summary": "Open the chat window to the position of the message", + "description": "", + "parameters": [ + { + "name": "sessionId", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Unique identifier for the session (alphanumeric and - allowed)", + "example": "f8377d8d-a589-4242-9ba6-9486a04ef80c" + } + ], + "responses": { + "200": { + "description": "OK" + }, + "403": { + "description": "Forbidden.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ForbiddenResponse" + } + } + } + }, + "404": { + "description": "Not Found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NotFoundResponse" + } + } + } + }, + "422": { + "description": "Unprocessable Entity.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Server failure.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + }, + "security": [ + { + "apiKeyAuth": [] + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "messageId": { + "type": "string", + "description": "ID of the message to scroll to (serialized)", + "example": "false_31235678901@c.us_3A40CB10BC3680B1EE" + } + } + } + }, + "application/xml": { + "schema": { + "type": "object", + "properties": { + "messageId": { + "type": "string", + "description": "ID of the message to scroll to (serialized)", + "example": "false_31235678901@c.us_3A40CB10BC3680B1EE" + } + } + } + } + } + } + } + }, + "/client/resetState/{sessionId}": { + "post": { + "tags": [ + "Client" + ], + "summary": "Force reset of connection state for the client", + "description": "", + "parameters": [ + { + "name": "sessionId", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Unique identifier for the session (alphanumeric and - allowed)", + "example": "f8377d8d-a589-4242-9ba6-9486a04ef80c" + } + ], + "responses": { + "200": { + "description": "OK" + }, + "403": { + "description": "Forbidden.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ForbiddenResponse" + } + } + } + }, + "404": { + "description": "Not Found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NotFoundResponse" + } + } + } + }, + "422": { + "description": "Unprocessable Entity.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Server failure.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + }, + "security": [ + { + "apiKeyAuth": [] + } + ] + } + }, + "/client/setBackgroundSync/{sessionId}": { + "post": { + "tags": [ + "Client" + ], + "summary": "Change the background synchronization setting", + "description": "NOTE: This action will take effect after you restart the client", + "parameters": [ + { + "name": "sessionId", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Unique identifier for the session (alphanumeric and - allowed)", + "example": "f8377d8d-a589-4242-9ba6-9486a04ef80c" + } + ], + "responses": { + "200": { + "description": "OK" + }, + "403": { + "description": "Forbidden.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ForbiddenResponse" + } + } + } + }, + "404": { + "description": "Not Found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NotFoundResponse" + } + } + } + }, + "422": { + "description": "Unprocessable Entity.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Server failure.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + }, + "security": [ + { + "apiKeyAuth": [] + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "flag": { + "type": "boolean", + "description": "flag true/false", + "example": true + } + } + } + }, + "application/xml": { + "schema": { + "type": "object", + "properties": { + "flag": { + "type": "boolean", + "description": "flag true/false", + "example": true + } + } + } + } + } + } + } + }, "/chat/getClassInfo/{sessionId}": { "post": { "tags": [ @@ -8524,6 +8795,11 @@ "type": "boolean", "description": "If true and the message is sent by the current user or the user is an admin, will delete it for everyone in the chat.", "example": true + }, + "clearMedia": { + "type": "boolean", + "description": "If true, any associated media will also be deleted from a device", + "example": true } } } @@ -8546,6 +8822,11 @@ "type": "boolean", "description": "If true and the message is sent by the current user or the user is an admin, will delete it for everyone in the chat.", "example": true + }, + "clearMedia": { + "type": "boolean", + "description": "If true, any associated media will also be deleted from a device", + "example": true } } }