From 2f4b5f70998879f8a9545f6e544e8007096ceddb Mon Sep 17 00:00:00 2001 From: Anton Voylenko Date: Fri, 6 Dec 2024 15:04:00 +0200 Subject: [PATCH] feat: fix and add missing client methods --- src/controllers/clientController.js | 459 +++++++++++++- src/routes.js | 9 + swagger.json | 944 ++++++++++++++++++++++++++-- 3 files changed, 1348 insertions(+), 64 deletions(-) diff --git a/src/controllers/clientController.js b/src/controllers/clientController.js index 399268e..90c5add 100644 --- a/src/controllers/clientController.js +++ b/src/controllers/clientController.js @@ -20,6 +20,7 @@ const { sendErrorResponse } = require('../utils') */ const sendMessage = async (req, res) => { /* + #swagger.summary = 'Send a message to a specific chatId' #swagger.requestBody = { required: true, '@content': { @@ -33,7 +34,7 @@ const sendMessage = async (req, res) => { }, contentType: { type: 'string', - description: 'The type of message content, must be one of the following: string, MessageMedia, MessageMediaFromURL, Location, Buttons, or List', + description: 'The type of message content, must be one of the following: string, MessageMedia, MessageMediaFromURL, Location, Contact, Poll, Buttons, or List', }, content: { type: 'object', @@ -131,7 +132,6 @@ const sendMessage = async (req, res) => { /** * Get session information for a given sessionId * - * @async * @function getClientInfo * @param {Object} req - Express request object * @param {Object} res - Express response object @@ -139,10 +139,13 @@ const sendMessage = async (req, res) => { * @returns {Object} - Response object with session info * @throws Will throw an error if session info cannot be retrieved */ -const getClassInfo = async (req, res) => { +const getClassInfo = (req, res) => { + /* + #swagger.summary = 'Get current connection information' + */ try { const client = sessions.get(req.params.sessionId) - const sessionInfo = await client.info + const sessionInfo = client.info res.json({ success: true, sessionInfo }) } catch (error) { sendErrorResponse(res, 500, error.message) @@ -163,6 +166,7 @@ const getClassInfo = async (req, res) => { */ const isRegisteredUser = async (req, res) => { /* + #swagger.summary = 'Check if a given ID is registered in WhatsApp' #swagger.requestBody = { required: true, schema: { @@ -201,6 +205,8 @@ const isRegisteredUser = async (req, res) => { */ const getNumberId = async (req, res) => { /* + #swagger.summary = 'Get the registered WhatsApp ID for a number' + #swagger.description = 'Return null if the number is not registered on WhatsApp' #swagger.requestBody = { required: true, schema: { @@ -239,10 +245,41 @@ const getNumberId = async (req, res) => { * @throws Will throw an error if group cannot be created */ const createGroup = async (req, res) => { + /* + #swagger.summary = 'Create a new group' + #swagger.requestBody = { + required: true, + schema: { + type: 'object', + properties: { + title: { + type: 'string', + description: 'Group title', + example: 'Group name' + }, + participants: { + type: 'array', + description: 'A single contact ID as a string or an array of contact IDs to add to the group', + example: [] + }, + options: { + type: 'array', + description: 'An object that handles options for group creation', + example: {} + }, + } + }, + } + */ try { - const { name, participants } = req.body + const { title, participants, options = {} } = req.body const client = sessions.get(req.params.sessionId) - const response = await client.createGroup(name, participants) + let response + if (Object.keys(options).length) { + response = await client.createGroup(title, participants, options) + } else { + response = await client.createGroup(title, participants) + } res.json({ success: true, response }) } catch (error) { sendErrorResponse(res, 500, error.message) @@ -263,6 +300,7 @@ const createGroup = async (req, res) => { */ const setStatus = async (req, res) => { /* + #swagger.summary = "Set the current user's status message" #swagger.requestBody = { required: true, schema: { @@ -297,6 +335,9 @@ const setStatus = async (req, res) => { * @returns {Promise} - A Promise that resolves with the retrieved contacts or rejects with an error. */ const getContacts = async (req, res) => { + /* + #swagger.summary = 'Get all current contacts' + */ try { const client = sessions.get(req.params.sessionId) const contacts = await client.getContacts() @@ -321,6 +362,9 @@ const getContacts = async (req, res) => { * @throws {Error} If the operation fails, an error is thrown. */ const getChats = async (req, res) => { + /* + #swagger.summary = 'Get all current chats' + */ try { const client = sessions.get(req.params.sessionId) const chats = await client.getChats() @@ -344,6 +388,7 @@ const getChats = async (req, res) => { */ const getProfilePictureUrl = async (req, res) => { /* + #swagger.summary = "Return the contact ID's profile picture URL" #swagger.requestBody = { required: true, schema: { @@ -383,6 +428,7 @@ const getProfilePictureUrl = async (req, res) => { */ const acceptInvite = async (req, res) => { /* + #swagger.summary = 'Accept an invitation to join a group' #swagger.requestBody = { required: true, schema: { @@ -420,6 +466,9 @@ const acceptInvite = async (req, res) => { * @throws {Error} If there is an error while accepting the invite. */ const getWWebVersion = async (req, res) => { + /* + #swagger.summary = 'Return the version of WhatsApp Web currently being run' + */ try { const client = sessions.get(req.params.sessionId) const result = await client.getWWebVersion() @@ -444,6 +493,7 @@ const getWWebVersion = async (req, res) => { */ const archiveChat = async (req, res) => { /* + #swagger.summary = 'Archive the chat' #swagger.requestBody = { required: true, schema: { @@ -480,6 +530,9 @@ const archiveChat = async (req, res) => { * @throws {Error} - Throws an error if the operation fails. */ const getBlockedContacts = async (req, res) => { + /* + #swagger.summary = 'Get all blocked contacts by host account' + */ try { const client = sessions.get(req.params.sessionId) const blockedContacts = await client.getBlockedContacts() @@ -503,6 +556,7 @@ const getBlockedContacts = async (req, res) => { */ const getChatById = async (req, res) => { /* + #swagger.summary = 'Get the chat' #swagger.requestBody = { required: true, schema: { @@ -541,6 +595,7 @@ const getChatById = async (req, res) => { */ const getChatLabels = async (req, res) => { /* + #swagger.summary = 'Get all labels assigned to the chat' #swagger.requestBody = { required: true, schema: { @@ -579,6 +634,7 @@ const getChatLabels = async (req, res) => { */ const getChatsByLabelId = async (req, res) => { /* + #swagger.summary = 'Get all chats for a specific label' #swagger.requestBody = { required: true, schema: { @@ -616,6 +672,8 @@ const getChatsByLabelId = async (req, res) => { */ const getCommonGroups = async (req, res) => { /* + #swagger.summary = "Get the contact's common groups" + #swagger.description = "Get the contact's common groups with you. Returns empty array if you don't have any common group." #swagger.requestBody = { required: true, schema: { @@ -653,6 +711,7 @@ const getCommonGroups = async (req, res) => { */ const getContactById = async (req, res) => { /* + #swagger.summary = 'Get the contact' #swagger.requestBody = { required: true, schema: { @@ -690,6 +749,8 @@ const getContactById = async (req, res) => { */ const getInviteInfo = async (req, res) => { /* + #swagger.summary = 'Return invite information' + #swagger.description = 'Return an object with information about the invite code's group' #swagger.requestBody = { required: true, schema: { @@ -728,6 +789,7 @@ const getInviteInfo = async (req, res) => { */ const getLabelById = async (req, res) => { /* + #swagger.summary = 'Get the label' #swagger.requestBody = { required: true, schema: { @@ -763,6 +825,9 @@ const getLabelById = async (req, res) => { * @throws {Error} If there is an error retrieving the labels. */ const getLabels = async (req, res) => { + /* + #swagger.summary = 'Get all current labels' + */ try { const client = sessions.get(req.params.sessionId) const labels = await client.getLabels() @@ -783,6 +848,7 @@ const getLabels = async (req, res) => { */ const addOrRemoveLabels = async (req, res) => { /* + #swagger.summary = 'Change labels in chats' #swagger.requestBody = { required: true, schema: { @@ -801,12 +867,12 @@ const addOrRemoveLabels = async (req, res) => { } }, } -*/ + */ try { const { labelIds, chatIds } = req.body const client = sessions.get(req.params.sessionId) - const labels = await client.addOrRemoveLabels(labelIds, chatIds) - res.json({ success: true, labels }) + await client.addOrRemoveLabels(labelIds, chatIds) + res.json({ success: true }) } catch (error) { sendErrorResponse(res, 500, error.message) } @@ -823,6 +889,9 @@ const addOrRemoveLabels = async (req, res) => { * @throws {Error} If there is an error retrieving the state. */ const getState = async (req, res) => { + /* + #swagger.summary = 'Get the current connection state for the client' + */ try { const client = sessions.get(req.params.sessionId) const state = await client.getState() @@ -846,6 +915,7 @@ const getState = async (req, res) => { */ const markChatUnread = async (req, res) => { /* + #swagger.summary = 'Mark the chat as unread' #swagger.requestBody = { required: true, schema: { @@ -863,8 +933,8 @@ const markChatUnread = async (req, res) => { try { const { chatId } = req.body const client = sessions.get(req.params.sessionId) - const mark = await client.markChatUnread(chatId) - res.json({ success: true, mark }) + await client.markChatUnread(chatId) + res.json({ success: true }) } catch (error) { sendErrorResponse(res, 500, error.message) } @@ -885,6 +955,8 @@ const markChatUnread = async (req, res) => { */ const muteChat = async (req, res) => { /* + #swagger.summary = 'Mute the chat' + #swagger.description = 'Mute this chat forever, unless a date is specified' #swagger.requestBody = { required: true, schema: { @@ -897,8 +969,8 @@ const muteChat = async (req, res) => { }, unmuteDate: { type: 'string', - description: 'Date when the chat will be muted, leave as is to mute forever', - example: '' + description: 'Timestamp when the chat will be muted, leave as is to mute forever', + example: '1733489397' }, } }, @@ -907,13 +979,12 @@ const muteChat = async (req, res) => { try { const { chatId, unmuteDate } = req.body const client = sessions.get(req.params.sessionId) - let mute if (unmuteDate) { - mute = await client.muteChat(chatId, new Date(unmuteDate)) + await client.muteChat(chatId, new Date(unmuteDate * 1000)) } else { - mute = await client.muteChat(chatId, null) + await client.muteChat(chatId, null) } - res.json({ success: true, mute }) + res.json({ success: true }) } catch (error) { sendErrorResponse(res, 500, error.message) } @@ -933,6 +1004,7 @@ const muteChat = async (req, res) => { */ const pinChat = async (req, res) => { /* + #swagger.summary = 'Pin the chat' #swagger.requestBody = { required: true, schema: { @@ -971,6 +1043,7 @@ const pinChat = async (req, res) => { */ const searchMessages = async (req, res) => { /* + #swagger.summary = 'Search for messages' #swagger.requestBody = { required: true, schema: { @@ -1016,10 +1089,13 @@ const searchMessages = async (req, res) => { * @throws {Error} - If there's an error during the presence sending. */ const sendPresenceAvailable = async (req, res) => { + /* + #swagger.summary = 'Mark the client as online' + */ try { const client = sessions.get(req.params.sessionId) - const presence = await client.sendPresenceAvailable() - res.json({ success: true, presence }) + await client.sendPresenceAvailable() + res.json({ success: true }) } catch (error) { sendErrorResponse(res, 500, error.message) } @@ -1036,10 +1112,13 @@ const sendPresenceAvailable = async (req, res) => { * @throws {Error} - If there's an error during the presence sending. */ const sendPresenceUnavailable = async (req, res) => { + /* + #swagger.summary = 'Mark the client as unavailable' + */ try { const client = sessions.get(req.params.sessionId) - const presence = await client.sendPresenceUnavailable() - res.json({ success: true, presence }) + await client.sendPresenceUnavailable() + res.json({ success: true }) } catch (error) { sendErrorResponse(res, 500, error.message) } @@ -1058,6 +1137,7 @@ const sendPresenceUnavailable = async (req, res) => { */ const sendSeen = async (req, res) => { /* + #swagger.summary = 'Mark the chat as seen' #swagger.requestBody = { required: true, schema: { @@ -1095,6 +1175,8 @@ const sendSeen = async (req, res) => { */ const setDisplayName = async (req, res) => { /* + #swagger.summary = 'Set the current user's display name' + #swagger.description = 'This is the name shown to WhatsApp users that have not added you as a contact beside your number in groups and in your profile.' #swagger.requestBody = { required: true, schema: { @@ -1132,6 +1214,7 @@ const setDisplayName = async (req, res) => { */ const unarchiveChat = async (req, res) => { /* + #swagger.summary = 'Changes archive state of the chat' #swagger.requestBody = { required: true, schema: { @@ -1170,6 +1253,7 @@ const unarchiveChat = async (req, res) => { */ const unmuteChat = async (req, res) => { /* + #swagger.summary = 'Unmute the chat' #swagger.requestBody = { required: true, schema: { @@ -1208,6 +1292,7 @@ const unmuteChat = async (req, res) => { */ const unpinChat = async (req, res) => { /* + #swagger.summary = 'Unpin the chat' #swagger.requestBody = { required: true, schema: { @@ -1233,7 +1318,7 @@ const unpinChat = async (req, res) => { } /** - * update the profile Picture of the session user + * Update the profile Picture of the session user * @param {Object} req - The request object. * @param {Object} res - The response object. * @param {Object} req.body.media - The new profile picture to set for the user's WhatsApp account. @@ -1244,6 +1329,7 @@ const unpinChat = async (req, res) => { const setProfilePicture = async (req, res) => { /* + #swagger.summary = 'Set the current user's profile picture' #swagger.requestBody = { required: true, schema: { @@ -1275,6 +1361,324 @@ const setProfilePicture = async (req, res) => { } } +/** + * Delete the profile Picture of the session user + * @param {Object} req - The request object. + * @param {Object} res - The response object. + * @returns {Object} Returns a JSON object with a success status and the result of the function. + * @throws {Error} If there is an issue deleting the profile picture, an error will be thrown. + */ + +const deleteProfilePicture = async (req, res) => { + /* + #swagger.summary = "Delete the current user's profile picture" + */ + try { + const client = sessions.get(req.params.sessionId) + const result = await client.deleteProfilePicture() + res.json({ success: true, result }) + } catch (error) { + sendErrorResponse(res, 500, error.message) + } +} + +/** + * Set auto load download audio value + * @param {Object} req - The request object. + * @param {Object} res - The response object. + * @returns {Object} Returns a JSON object with a success status and the result of the function. + * @throws {Error} If there is an issue deleting the profile picture, an error will be thrown. + */ + +const setAutoDownloadAudio = async (req, res) => { + /* + #swagger.summary = 'Set auto load download audio flag' + #swagger.requestBody = { + required: true, + schema: { + type: 'object', + properties: { + flag: { + type: 'boolean', + description: 'Flag true/false', + example: true + }, + } + }, + } + */ + try { + const { flag } = req.body + const client = sessions.get(req.params.sessionId) + await client.setAutoDownloadAudio(flag) + res.json({ success: true }) + } catch (error) { + sendErrorResponse(res, 500, error.message) + } +} + +/** + * Set auto load download documents value + * @param {Object} req - The request object. + * @param {Object} res - The response object. + * @returns {Object} Returns a JSON object with a success status and the result of the function. + * @throws {Error} If there is an issue deleting the profile picture, an error will be thrown. + */ + +const setAutoDownloadDocuments = async (req, res) => { + /* + #swagger.summary = 'Set auto load download documents flag' + #swagger.requestBody = { + required: true, + schema: { + type: 'object', + properties: { + flag: { + type: 'boolean', + description: 'Flag true/false', + example: true + }, + } + }, + } + */ + try { + const { flag } = req.body + const client = sessions.get(req.params.sessionId) + await client.setAutoDownloadDocuments(flag) + res.json({ success: true }) + } catch (error) { + sendErrorResponse(res, 500, error.message) + } +} + +/** + * Set auto load download photos value + * @param {Object} req - The request object. + * @param {Object} res - The response object. + * @returns {Object} Returns a JSON object with a success status and the result of the function. + * @throws {Error} If there is an issue deleting the profile picture, an error will be thrown. + */ + +const setAutoDownloadPhotos = async (req, res) => { + /* + #swagger.summary = 'Set auto load download photos flag' + #swagger.requestBody = { + required: true, + schema: { + type: 'object', + properties: { + flag: { + type: 'boolean', + description: 'Flag true/false', + example: true + }, + } + }, + } + */ + try { + const { flag } = req.body + const client = sessions.get(req.params.sessionId) + await client.setAutoDownloadPhotos(flag) + res.json({ success: true }) + } catch (error) { + sendErrorResponse(res, 500, error.message) + } +} + +/** + * Set auto load download videos value + * @param {Object} req - The request object. + * @param {Object} res - The response object. + * @returns {Object} Returns a JSON object with a success status and the result of the function. + * @throws {Error} If there is an issue deleting the profile picture, an error will be thrown. + */ + +const setAutoDownloadVideos = async (req, res) => { + /* + #swagger.summary = 'Set auto load download videos flag' + #swagger.requestBody = { + required: true, + schema: { + type: 'object', + properties: { + flag: { + type: 'boolean', + description: 'Flag true/false', + example: true + }, + } + }, + } + */ + try { + const { flag } = req.body + const client = sessions.get(req.params.sessionId) + await client.setAutoDownloadVideos(flag) + res.json({ success: true }) + } catch (error) { + sendErrorResponse(res, 500, error.message) + } +} + +/** + * Sync chat history conversation. + * + * @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 syncHistory = async (req, res) => { + /* + #swagger.summary = 'Sync chat history' + #swagger.requestBody = { + required: true, + schema: { + type: 'object', + properties: { + chatId: { + type: 'string', + description: 'ID of the chat', + example: '' + }, + } + }, + } + */ + try { + const { chatId } = req.body + const client = sessions.get(req.params.sessionId) + const result = await client.syncHistory(chatId) + res.json({ success: true, result }) + } catch (error) { + sendErrorResponse(res, 500, error.message) + } +} + +/** + * Get user device count by ID. + * + * @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 getContactDeviceCount = async (req, res) => { + /* + #swagger.summary = 'Get user device count' + #swagger.description = 'Each WaWeb Connection counts as one device, and the phone (if exists) counts as one device. So for a non-enterprise user with one WaWeb connection it should return "2"' + #swagger.requestBody = { + required: true, + schema: { + type: 'object', + properties: { + userId: { + type: 'string', + description: 'ID of the user', + example: '' + }, + } + }, + } + */ + try { + const { userId } = req.body + const client = sessions.get(req.params.sessionId) + const result = await client.getContactDeviceCount(userId) + res.json({ success: true, result }) + } catch (error) { + sendErrorResponse(res, 500, error.message) + } +} + +/** + * Get the country code of a WhatsApp ID. + * + * @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 getCountryCode = async (req, res) => { + /* + #swagger.summary = 'Get the country code' + #swagger.requestBody = { + required: true, + schema: { + type: 'object', + properties: { + number: { + type: 'string', + description: 'Number or ID', + example: '' + }, + } + }, + } + */ + try { + const { number } = req.body + const client = sessions.get(req.params.sessionId) + const result = await client.getCountryCode(number) + res.json({ success: true, result }) + } catch (error) { + sendErrorResponse(res, 500, error.message) + } +} + +/** + * Get the formatted number of a WhatsApp ID. + * + * @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 getFormattedNumber = async (req, res) => { + /* + #swagger.summary = 'Get the formatted number' + #swagger.requestBody = { + required: true, + schema: { + type: 'object', + properties: { + number: { + type: 'string', + description: 'Number or ID', + example: '' + }, + } + }, + } + */ + try { + const { number } = req.body + const client = sessions.get(req.params.sessionId) + const result = await client.getFormattedNumber(number) + res.json({ success: true, result }) + } catch (error) { + sendErrorResponse(res, 500, error.message) + } +} + module.exports = { getClassInfo, acceptInvite, @@ -1310,5 +1714,14 @@ module.exports = { unarchiveChat, unmuteChat, unpinChat, - getWWebVersion + getWWebVersion, + deleteProfilePicture, + setAutoDownloadAudio, + setAutoDownloadDocuments, + setAutoDownloadPhotos, + setAutoDownloadVideos, + syncHistory, + getContactDeviceCount, + getCountryCode, + getFormattedNumber } diff --git a/src/routes.js b/src/routes.js index 8f0ffdd..01786d7 100644 --- a/src/routes.js +++ b/src/routes.js @@ -91,6 +91,15 @@ clientRouter.post('/unarchiveChat/:sessionId', [middleware.sessionNameValidation clientRouter.post('/unmuteChat/:sessionId', [middleware.sessionNameValidation, middleware.sessionValidation], clientController.unmuteChat) clientRouter.post('/unpinChat/:sessionId', [middleware.sessionNameValidation, middleware.sessionValidation], clientController.unpinChat) clientRouter.get('/getWWebVersion/:sessionId', [middleware.sessionNameValidation, middleware.sessionValidation], clientController.getWWebVersion) +clientRouter.delete('/deleteProfilePicture/:sessionId', [middleware.sessionNameValidation, middleware.sessionValidation], clientController.deleteProfilePicture) +clientRouter.post('/setAutoDownloadAudio/:sessionId', [middleware.sessionNameValidation, middleware.sessionValidation], clientController.setAutoDownloadAudio) +clientRouter.post('/setAutoDownloadDocuments/:sessionId', [middleware.sessionNameValidation, middleware.sessionValidation], clientController.setAutoDownloadDocuments) +clientRouter.post('/setAutoDownloadPhotos/:sessionId', [middleware.sessionNameValidation, middleware.sessionValidation], clientController.setAutoDownloadPhotos) +clientRouter.post('/setAutoDownloadVideos/:sessionId', [middleware.sessionNameValidation, middleware.sessionValidation], clientController.setAutoDownloadVideos) +clientRouter.post('/syncHistory/:sessionId', [middleware.sessionNameValidation, middleware.sessionValidation], clientController.syncHistory) +clientRouter.post('/getContactDeviceCount/:sessionId', [middleware.sessionNameValidation, middleware.sessionValidation], clientController.getContactDeviceCount) +clientRouter.post('/getCountryCode/:sessionId', [middleware.sessionNameValidation, middleware.sessionValidation], clientController.getCountryCode) +clientRouter.post('/getFormattedNumber/:sessionId', [middleware.sessionNameValidation, middleware.sessionValidation], clientController.getFormattedNumber) /** * ================ diff --git a/swagger.json b/swagger.json index 36dbc91..69dff6b 100644 --- a/swagger.json +++ b/swagger.json @@ -601,6 +601,7 @@ "tags": [ "Client" ], + "summary": "Get current connection information", "description": "", "parameters": [ { @@ -661,6 +662,7 @@ "tags": [ "Client" ], + "summary": "Accept an invitation to join a group", "description": "", "parameters": [ { @@ -750,6 +752,7 @@ "tags": [ "Client" ], + "summary": "Archive the chat", "description": "", "parameters": [ { @@ -839,6 +842,7 @@ "tags": [ "Client" ], + "summary": "Create a new group", "description": "", "parameters": [ { @@ -891,7 +895,56 @@ { "apiKeyAuth": [] } - ] + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "title": { + "type": "string", + "description": "Group title", + "example": "Group name" + }, + "participants": { + "type": "array", + "description": "A single contact ID as a string or an array of contact IDs to add to the group", + "example": [] + }, + "options": { + "type": "array", + "description": "An object that handles options for group creation", + "example": {} + } + } + } + }, + "application/xml": { + "schema": { + "type": "object", + "properties": { + "title": { + "type": "string", + "description": "Group title", + "example": "Group name" + }, + "participants": { + "type": "array", + "description": "A single contact ID as a string or an array of contact IDs to add to the group", + "example": [] + }, + "options": { + "type": "array", + "description": "An object that handles options for group creation", + "example": {} + } + } + } + } + } + } } }, "/client/getBlockedContacts/{sessionId}": { @@ -899,6 +952,7 @@ "tags": [ "Client" ], + "summary": "Get all blocked contacts by host account", "description": "", "parameters": [ { @@ -959,6 +1013,7 @@ "tags": [ "Client" ], + "summary": "Get the chat", "description": "", "parameters": [ { @@ -1048,6 +1103,7 @@ "tags": [ "Client" ], + "summary": "Get all labels assigned to the chat", "description": "", "parameters": [ { @@ -1137,6 +1193,7 @@ "tags": [ "Client" ], + "summary": "Get all current chats", "description": "", "parameters": [ { @@ -1197,6 +1254,7 @@ "tags": [ "Client" ], + "summary": "Get all chats for a specific label", "description": "", "parameters": [ { @@ -1286,7 +1344,8 @@ "tags": [ "Client" ], - "description": "", + "summary": "Get the contact's common groups", + "description": "Get the contact's common groups with you. Returns empty array if you don't have any common group.", "parameters": [ { "name": "sessionId", @@ -1375,6 +1434,7 @@ "tags": [ "Client" ], + "summary": "Get the contact", "description": "", "parameters": [ { @@ -1464,6 +1524,7 @@ "tags": [ "Client" ], + "summary": "Get all current contacts", "description": "", "parameters": [ { @@ -1524,7 +1585,8 @@ "tags": [ "Client" ], - "description": "", + "summary": "Return invite information", + "description": "Return an object with information about the invite code", "parameters": [ { "name": "sessionId", @@ -1584,9 +1646,9 @@ "schema": { "type": "object", "properties": { - "inviteCode": { + "displayName": { "type": "string", - "description": "Invitation code", + "description": "New display name", "example": "" } } @@ -1596,9 +1658,9 @@ "schema": { "type": "object", "properties": { - "inviteCode": { + "displayName": { "type": "string", - "description": "Invitation code", + "description": "New display name", "example": "" } } @@ -1613,6 +1675,7 @@ "tags": [ "Client" ], + "summary": "Get the label", "description": "", "parameters": [ { @@ -1702,6 +1765,7 @@ "tags": [ "Client" ], + "summary": "Get all current labels", "description": "", "parameters": [ { @@ -1762,6 +1826,7 @@ "tags": [ "Client" ], + "summary": "Change labels in chats", "description": "", "parameters": [ { @@ -1861,7 +1926,8 @@ "tags": [ "Client" ], - "description": "", + "summary": "Get the registered WhatsApp ID for a number", + "description": "Return null if the number is not registered on WhatsApp", "parameters": [ { "name": "sessionId", @@ -1950,6 +2016,7 @@ "tags": [ "Client" ], + "summary": "Check if a given ID is registered in WhatsApp", "description": "", "parameters": [ { @@ -2039,6 +2106,7 @@ "tags": [ "Client" ], + "summary": "Return the contact ID's profile picture URL", "description": "", "parameters": [ { @@ -2128,6 +2196,7 @@ "tags": [ "Client" ], + "summary": "Get the current connection state for the client", "description": "", "parameters": [ { @@ -2178,6 +2247,7 @@ "tags": [ "Client" ], + "summary": "Mark the chat as unread", "description": "", "parameters": [ { @@ -2267,7 +2337,8 @@ "tags": [ "Client" ], - "description": "", + "summary": "Mute the chat", + "description": "Mute this chat forever, unless a date is specified", "parameters": [ { "name": "sessionId", @@ -2334,8 +2405,8 @@ }, "unmuteDate": { "type": "string", - "description": "Date when the chat will be muted, leave as is to mute forever", - "example": "" + "description": "Timestamp when the chat will be muted, leave as is to mute forever", + "example": "1733489397" } } } @@ -2351,8 +2422,8 @@ }, "unmuteDate": { "type": "string", - "description": "Date when the chat will be muted, leave as is to mute forever", - "example": "" + "description": "Timestamp when the chat will be muted, leave as is to mute forever", + "example": "1733489397" } } } @@ -2366,6 +2437,7 @@ "tags": [ "Client" ], + "summary": "Pin the chat", "description": "", "parameters": [ { @@ -2455,6 +2527,7 @@ "tags": [ "Client" ], + "summary": "Search for messages", "description": "", "parameters": [ { @@ -2554,6 +2627,7 @@ "tags": [ "Client" ], + "summary": "Send a message to a specific chatId", "description": "", "parameters": [ { @@ -2620,7 +2694,7 @@ }, "contentType": { "type": "string", - "description": "The type of message content, must be one of the following: string, MessageMedia, MessageMediaFromURL, Location, Buttons, or List" + "description": "The type of message content, must be one of the following: string, MessageMedia, MessageMediaFromURL, Location, Contact, Poll, Buttons, or List" }, "content": { "type": "object", @@ -2748,6 +2822,7 @@ "tags": [ "Client" ], + "summary": "Mark the client as online", "description": "", "parameters": [ { @@ -2808,6 +2883,7 @@ "tags": [ "Client" ], + "summary": "Mark the client as unavailable", "description": "", "parameters": [ { @@ -2868,6 +2944,7 @@ "tags": [ "Client" ], + "summary": "Mark the chat as seen", "description": "", "parameters": [ { @@ -2957,7 +3034,8 @@ "tags": [ "Client" ], - "description": "", + "summary": "Set the current user", + "description": "This is the name shown to WhatsApp users that have not added you as a contact beside your number in groups and in your profile.", "parameters": [ { "name": "sessionId", @@ -3017,10 +3095,15 @@ "schema": { "type": "object", "properties": { - "displayName": { + "pictureMimetype": { "type": "string", - "description": "New display name", - "example": "" + "description": "The mimetype of the picture to set as the profile picture for the user WhatsApp account.", + "example": "image/png" + }, + "pictureData": { + "type": "string", + "description": "The base64 data of the picture to set as the profile picture for the user WhatsApp account.", + "example": "iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX +/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII=" } } } @@ -3029,10 +3112,15 @@ "schema": { "type": "object", "properties": { - "displayName": { + "pictureMimetype": { "type": "string", - "description": "New display name", - "example": "" + "description": "The mimetype of the picture to set as the profile picture for the user WhatsApp account.", + "example": "image/png" + }, + "pictureData": { + "type": "string", + "description": "The base64 data of the picture to set as the profile picture for the user WhatsApp account.", + "example": "iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX +/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII=" } } } @@ -3046,7 +3134,8 @@ "tags": [ "Client" ], - "description": "", + "summary": "Set the current user", + "description": "Each WaWeb Connection counts as one device, and the phone (if exists) counts as one device. So for a non-enterprise user with one WaWeb connection it should return \"2\"", "parameters": [ { "name": "sessionId", @@ -3060,9 +3149,6 @@ } ], "responses": { - "200": { - "description": "OK" - }, "403": { "description": "Forbidden.", "content": { @@ -3106,15 +3192,10 @@ "schema": { "type": "object", "properties": { - "pictureMimetype": { + "number": { "type": "string", - "description": "The mimetype of the picture to set as the profile picture for the user WhatsApp account.", - "example": "image/png" - }, - "pictureData": { - "type": "string", - "description": "The base64 data of the picture to set as the profile picture for the user WhatsApp account.", - "example": "iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX +/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII=" + "description": "Number or ID", + "example": "" } } } @@ -3123,15 +3204,10 @@ "schema": { "type": "object", "properties": { - "pictureMimetype": { + "number": { "type": "string", - "description": "The mimetype of the picture to set as the profile picture for the user WhatsApp account.", - "example": "image/png" - }, - "pictureData": { - "type": "string", - "description": "The base64 data of the picture to set as the profile picture for the user WhatsApp account.", - "example": "iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX +/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII=" + "description": "Number or ID", + "example": "" } } } @@ -3145,6 +3221,7 @@ "tags": [ "Client" ], + "summary": "Set the current user's status message", "description": "", "parameters": [ { @@ -3234,6 +3311,7 @@ "tags": [ "Client" ], + "summary": "Changes archive state of the chat", "description": "", "parameters": [ { @@ -3323,6 +3401,7 @@ "tags": [ "Client" ], + "summary": "Unmute the chat", "description": "", "parameters": [ { @@ -3412,6 +3491,7 @@ "tags": [ "Client" ], + "summary": "Unpin the chat", "description": "", "parameters": [ { @@ -3501,6 +3581,7 @@ "tags": [ "Client" ], + "summary": "Return the version of WhatsApp Web currently being run", "description": "", "parameters": [ { @@ -3556,6 +3637,787 @@ ] } }, + "/client/deleteProfilePicture/{sessionId}": { + "delete": { + "tags": [ + "Client" + ], + "summary": "Delete the current user's profile picture", + "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" + } + } + } + } + }, + "security": [ + { + "apiKeyAuth": [] + } + ] + } + }, + "/client/setAutoDownloadAudio/{sessionId}": { + "post": { + "tags": [ + "Client" + ], + "summary": "Set auto load download audio flag", + "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" + } + } + } + } + }, + "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 + } + } + } + } + } + } + } + }, + "/client/setAutoDownloadDocuments/{sessionId}": { + "post": { + "tags": [ + "Client" + ], + "summary": "Set auto load download documents flag", + "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" + } + } + } + } + }, + "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 + } + } + } + } + } + } + } + }, + "/client/setAutoDownloadPhotos/{sessionId}": { + "post": { + "tags": [ + "Client" + ], + "summary": "Set auto load download photos flag", + "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" + } + } + } + } + }, + "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 + } + } + } + } + } + } + } + }, + "/client/setAutoDownloadVideos/{sessionId}": { + "post": { + "tags": [ + "Client" + ], + "summary": "Set auto load download videos flag", + "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" + } + } + } + } + }, + "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 + } + } + } + } + } + } + } + }, + "/client/syncHistory/{sessionId}": { + "post": { + "tags": [ + "Client" + ], + "summary": "Sync chat history", + "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" + } + } + } + } + }, + "security": [ + { + "apiKeyAuth": [] + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "chatId": { + "type": "string", + "description": "ID of the chat", + "example": "" + } + } + } + }, + "application/xml": { + "schema": { + "type": "object", + "properties": { + "chatId": { + "type": "string", + "description": "ID of the chat", + "example": "" + } + } + } + } + } + } + } + }, + "/client/getContactDeviceCount/{sessionId}": { + "post": { + "tags": [ + "Client" + ], + "summary": "Get user device count", + "description": "Each WaWeb Connection counts as one device, and the phone (if exists) counts as one device. So for a non-enterprise user with one WaWeb connection it should return \"2\"", + "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" + } + } + } + } + }, + "security": [ + { + "apiKeyAuth": [] + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "ID of the user", + "example": "" + } + } + } + }, + "application/xml": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "ID of the user", + "example": "" + } + } + } + } + } + } + } + }, + "/client/getCountryCode/{sessionId}": { + "post": { + "tags": [ + "Client" + ], + "summary": "Get the country code", + "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" + } + } + } + } + }, + "security": [ + { + "apiKeyAuth": [] + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "number": { + "type": "string", + "description": "Number or ID", + "example": "" + } + } + } + }, + "application/xml": { + "schema": { + "type": "object", + "properties": { + "number": { + "type": "string", + "description": "Number or ID", + "example": "" + } + } + } + } + } + } + } + }, + "/client/getFormattedNumber/{sessionId}": { + "post": { + "tags": [ + "Client" + ], + "summary": "Get the formatted number", + "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" + } + } + } + } + }, + "security": [ + { + "apiKeyAuth": [] + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "number": { + "type": "string", + "description": "Number or ID", + "example": "" + } + } + } + }, + "application/xml": { + "schema": { + "type": "object", + "properties": { + "number": { + "type": "string", + "description": "Number or ID", + "example": "" + } + } + } + } + } + } + } + }, "/chat/getClassInfo/{sessionId}": { "post": { "tags": [