diff --git a/requirements.txt b/requirements.txt index 2c24336..1b10f94 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,2 @@ requests==2.31.0 +pydantic==2.5.3 diff --git a/whatsapp_api_client_python/API.py b/whatsapp_api_client_python/API.py index 815886b..d4965fc 100644 --- a/whatsapp_api_client_python/API.py +++ b/whatsapp_api_client_python/API.py @@ -32,6 +32,7 @@ def __init__( apiTokenInstance: str, debug_mode: bool = False, raise_errors: bool = False, + create_models: bool = False, host: str = "https://api.green-api.com", media: str = "https://media.green-api.com" ): @@ -39,6 +40,7 @@ def __init__( self.media = media self.debug_mode = debug_mode self.raise_errors = raise_errors + self.create_models = create_models self.idInstance = idInstance self.apiTokenInstance = apiTokenInstance @@ -88,11 +90,13 @@ def request( raise GreenAPIError(error_message) self.logger.log(logging.CRITICAL, error_message) - return GreenAPIResponse(None, error_message) + return GreenAPIResponse(None, error_message, self.create_models) self.__handle_response(response) - return GreenAPIResponse(response.status_code, response.text) + return GreenAPIResponse( + response.status_code, response.text, self.create_models + ) def raw_request(self, **arguments: Any) -> GreenAPIResponse: try: @@ -104,11 +108,13 @@ def raw_request(self, **arguments: Any) -> GreenAPIResponse: raise GreenAPIError(error_message) self.logger.log(logging.CRITICAL, error_message) - return GreenAPIResponse(None, error_message) + return GreenAPIResponse(None, error_message, self.create_models) self.__handle_response(response) - return GreenAPIResponse(response.status_code, response.text) + return GreenAPIResponse( + response.status_code, response.text, self.create_models + ) def __handle_response(self, response: Response) -> Optional[NoReturn]: status_code = response.status_code diff --git a/whatsapp_api_client_python/response.py b/whatsapp_api_client_python/response.py index 60e51ce..58f0a6b 100644 --- a/whatsapp_api_client_python/response.py +++ b/whatsapp_api_client_python/response.py @@ -1,15 +1,31 @@ from json import loads -from typing import Optional +from typing import Generic, Optional, Type, TypeVar +from .responses.base import BaseResponse -class Response: +Model = TypeVar("Model", bound=BaseResponse) + + +class Response(Generic[Model]): code: Optional[int] data: Optional[dict] = None error: Optional[str] = None - def __init__(self, code: Optional[int], text: str): + create_models: bool = False + model: Optional[Model] = None + + def __init__(self, code: Optional[int], text: str, create_models: bool): self.code = code if self.code == 200: self.data = loads(text) else: self.error = text + + self.create_models = create_models + + def create_model(self, response_type: Type[BaseResponse]) -> None: + if self.create_models: + self.model = response_type(**self.data) + + +__all__ = ["Response"] diff --git a/whatsapp_api_client_python/responses/__init__.py b/whatsapp_api_client_python/responses/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/whatsapp_api_client_python/responses/account.py b/whatsapp_api_client_python/responses/account.py new file mode 100644 index 0000000..1f2a241 --- /dev/null +++ b/whatsapp_api_client_python/responses/account.py @@ -0,0 +1,78 @@ +from typing import Optional + +from .base import BaseResponse + + +class GetSettingsResponse(BaseResponse): + wid: Optional[str] = None + webhook_url: Optional[str] = None + webhook_url_token: Optional[str] = None + delay_send_messages_milliseconds: Optional[int] = None + mark_incoming_messages_read: Optional[bool] = None + mark_incoming_messages_read_on_reply: Optional[bool] = None + outgoing_webhook: Optional[bool] = None + outgoing_message_webhook: Optional[bool] = None + outgoing_api_message_webhook: Optional[bool] = None + incoming_webhook: Optional[bool] = None + device_webhook: Optional[bool] = None + state_webhook: Optional[bool] = None + keep_online_status: Optional[bool] = None + poll_message_webhook: Optional[bool] = None + incoming_block_webhook: Optional[bool] = None + + +class GetWASettingsResponse(BaseResponse): + avatar: Optional[str] = None + phone: Optional[str] = None + state_instance: Optional[str] = None + device_id: Optional[str] = None + + +class SetSettingsResponse(BaseResponse): + save_settings: Optional[bool] = None + + +class GetStateInstanceResponse(BaseResponse): + state_instance: Optional[str] = None + + +class GetStatusInstanceResponse(BaseResponse): + status_instance: Optional[str] = None + + +class RebootResponse(BaseResponse): + is_reboot: Optional[bool] = None + + +class LogoutResponse(BaseResponse): + is_logout: Optional[bool] = None + + +class QRResponse(BaseResponse): + type: Optional[str] = None + message: Optional[str] = None + + +class SetProfilePictureResponse(BaseResponse): + reason: Optional[str] = None + url_avatar: Optional[str] = None + set_profile_picture: Optional[bool] = None + + +class GetAuthorizationCodeResponse(BaseResponse): + status: Optional[bool] = None + code: Optional[str] = None + + +__all__ = [ + "GetSettingsResponse", + "GetWASettingsResponse", + "SetSettingsResponse", + "GetStateInstanceResponse", + "GetStatusInstanceResponse", + "RebootResponse", + "LogoutResponse", + "QRResponse", + "SetProfilePictureResponse", + "GetAuthorizationCodeResponse" +] diff --git a/whatsapp_api_client_python/responses/base.py b/whatsapp_api_client_python/responses/base.py new file mode 100644 index 0000000..23da605 --- /dev/null +++ b/whatsapp_api_client_python/responses/base.py @@ -0,0 +1,9 @@ +from pydantic import BaseModel, ConfigDict +from pydantic.alias_generators import to_camel + + +class BaseResponse(BaseModel): + model_config = ConfigDict(alias_generator=to_camel) + + +__all__ = ["BaseResponse"] diff --git a/whatsapp_api_client_python/tools/account.py b/whatsapp_api_client_python/tools/account.py index b0013c4..a0d1565 100644 --- a/whatsapp_api_client_python/tools/account.py +++ b/whatsapp_api_client_python/tools/account.py @@ -1,31 +1,42 @@ from pathlib import Path -from typing import Dict, TYPE_CHECKING, Union +from typing import Dict, Union +from .base import BaseCategory from ..response import Response - -if TYPE_CHECKING: - from ..API import GreenApi - - -class Account: - def __init__(self, api: "GreenApi"): - self.api = api - - def getSettings(self) -> Response: +from ..responses.account import ( + GetAuthorizationCodeResponse, + GetSettingsResponse, + GetStateInstanceResponse, + GetStatusInstanceResponse, + GetWASettingsResponse, + LogoutResponse, + QRResponse, + RebootResponse, + SetProfilePictureResponse, + SetSettingsResponse +) + + +class Account(BaseCategory): + def getSettings(self) -> Response[GetSettingsResponse]: """ The method is aimed for getting the current account settings. https://green-api.com/en/docs/api/account/GetSettings/ """ - return self.api.request( + response = self.api.request( "GET", ( "{{host}}/waInstance{{idInstance}}/" "getSettings/{{apiTokenInstance}}" ) ) - def getWaSettings(self) -> Response: + response.create_model(GetSettingsResponse) + + return response + + def getWaSettings(self) -> Response[GetWASettingsResponse]: """ The method is aimed to get information about the WhatsApp account. @@ -33,42 +44,56 @@ def getWaSettings(self) -> Response: https://green-api.com/en/docs/api/account/GetWaSettings/ """ - return self.api.request( + response = self.api.request( "GET", ( "{{host}}/waInstance{{idInstance}}/" "getWaSettings/{{apiTokenInstance}}" ) ) - def setSettings(self, requestBody: Dict[str, Union[int, str]]) -> Response: + response.create_model(GetWASettingsResponse) + + return response + + def setSettings( + self, requestBody: Dict[str, Union[int, str]] + ) -> Response[SetSettingsResponse]: """ The method is aimed for setting account settings. https://green-api.com/en/docs/api/account/SetSettings/ """ - return self.api.request( + response = self.api.request( "POST", ( "{{host}}/waInstance{{idInstance}}/" "setSettings/{{apiTokenInstance}}" ), requestBody ) - def getStateInstance(self) -> Response: + response.create_model(SetSettingsResponse) + + return response + + def getStateInstance(self) -> Response[GetStateInstanceResponse]: """ The method is aimed for getting the account state. https://green-api.com/en/docs/api/account/GetStateInstance/ """ - return self.api.request( + response = self.api.request( "GET", ( "{{host}}/waInstance{{idInstance}}/" "getStateInstance/{{apiTokenInstance}}" ) ) - def getStatusInstance(self) -> Response: + response.create_model(GetStateInstanceResponse) + + return response + + def getStatusInstance(self) -> Response[GetStatusInstanceResponse]: """ The method is aimed for getting the status of the account instance socket connection with WhatsApp. @@ -76,51 +101,69 @@ def getStatusInstance(self) -> Response: https://green-api.com/en/docs/api/account/GetStatusInstance/ """ - return self.api.request( + response = self.api.request( "GET", ( "{{host}}/waInstance{{idInstance}}/" "getStatusInstance/{{apiTokenInstance}}" ) ) - def reboot(self) -> Response: + response.create_model(GetStatusInstanceResponse) + + return response + + def reboot(self) -> Response[RebootResponse]: """ The method is aimed for rebooting an account. https://green-api.com/en/docs/api/account/Reboot/ """ - return self.api.request( + response = self.api.request( "GET", ( "{{host}}/waInstance{{idInstance}}/reboot/{{apiTokenInstance}}" ) ) - def logout(self) -> Response: + response.create_model(RebootResponse) + + return response + + def logout(self) -> Response[LogoutResponse]: """ The method is aimed for logging out an account. https://green-api.com/en/docs/api/account/Logout/ """ - return self.api.request( + response = self.api.request( "GET", ( "{{host}}/waInstance{{idInstance}}/logout/{{apiTokenInstance}}" ) ) - def qr(self) -> Response: + response.create_model(LogoutResponse) + + return response + + def qr(self) -> Response[QRResponse]: """ The method is aimed for getting QR code. https://green-api.com/en/docs/api/account/QR/ """ - return self.api.request( + response = self.api.request( "GET", "{{host}}/waInstance{{idInstance}}/qr/{{apiTokenInstance}}" ) - def setProfilePicture(self, path: str) -> Response: + response.create_model(QRResponse) + + return response + + def setProfilePicture( + self, path: str + ) -> Response[SetProfilePictureResponse]: """ The method is aimed for setting an account picture. @@ -130,14 +173,20 @@ def setProfilePicture(self, path: str) -> Response: file_name = Path(path).name files = {"file": (file_name, open(path, "rb"), "image/jpeg")} - return self.api.request( + response = self.api.request( "POST", ( "{{host}}/waInstance{{idInstance}}/" "setProfilePicture/{{apiTokenInstance}}" ), files=files ) - def getAuthorizationCode(self, phoneNumber: int) -> Response: + response.create_model(SetProfilePictureResponse) + + return response + + def getAuthorizationCode( + self, phoneNumber: int + ) -> Response[GetAuthorizationCodeResponse]: """ The method is designed to authorize an instance by phone number. @@ -147,9 +196,16 @@ def getAuthorizationCode(self, phoneNumber: int) -> Response: request_body = locals() request_body.pop("self") - return self.api.request( + response = self.api.request( "POST", ( "{{host}}/waInstance{{idInstance}}/" "getAuthorizationCode/{{apiTokenInstance}}" ), request_body ) + + response.create_model(GetAuthorizationCodeResponse) + + return response + + +__all__ = ["Account"] diff --git a/whatsapp_api_client_python/tools/base.py b/whatsapp_api_client_python/tools/base.py new file mode 100644 index 0000000..bd9e77f --- /dev/null +++ b/whatsapp_api_client_python/tools/base.py @@ -0,0 +1,24 @@ +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from ..API import GreenApi + + +class BaseCategory: + def __init__(self, api: "GreenApi"): + self.api = api + + @classmethod + def _handle_parameters(cls, parameters: dict) -> dict: + handled_parameters = parameters.copy() + + handled_parameters.pop("self") + + for key, value in parameters.items(): + if value is None: + handled_parameters.pop(key) + + return handled_parameters + + +__all__ = ["BaseCategory"] diff --git a/whatsapp_api_client_python/tools/device.py b/whatsapp_api_client_python/tools/device.py index 04a42b8..58a0f63 100644 --- a/whatsapp_api_client_python/tools/device.py +++ b/whatsapp_api_client_python/tools/device.py @@ -1,15 +1,8 @@ -from typing import TYPE_CHECKING - +from .base import BaseCategory from ..response import Response -if TYPE_CHECKING: - from ..API import GreenApi - - -class Device: - def __init__(self, api: "GreenApi"): - self.api = api +class Device(BaseCategory): def getDeviceInfo(self) -> Response: """ The method is aimed for getting information about the device @@ -24,3 +17,6 @@ def getDeviceInfo(self) -> Response: "getDeviceInfo/{{apiTokenInstance}}" ) ) + + +__all__ = ["Device"] diff --git a/whatsapp_api_client_python/tools/groups.py b/whatsapp_api_client_python/tools/groups.py index ca3aba4..696eca2 100644 --- a/whatsapp_api_client_python/tools/groups.py +++ b/whatsapp_api_client_python/tools/groups.py @@ -1,16 +1,11 @@ from pathlib import Path -from typing import List, TYPE_CHECKING +from typing import List +from .base import BaseCategory from ..response import Response -if TYPE_CHECKING: - from ..API import GreenApi - - -class Groups: - def __init__(self, api: "GreenApi"): - self.api = api +class Groups(BaseCategory): def createGroup(self, groupName: str, chatIds: List[str]) -> Response: """ The method is aimed for creating a group chat. @@ -18,7 +13,7 @@ def createGroup(self, groupName: str, chatIds: List[str]) -> Response: https://green-api.com/en/docs/api/groups/CreateGroup/ """ - request_body = self.__handle_parameters(locals()) + request_body = self._handle_parameters(locals()) return self.api.request( "POST", ( @@ -34,7 +29,7 @@ def updateGroupName(self, groupId: str, groupName: str) -> Response: https://green-api.com/en/docs/api/groups/UpdateGroupName/ """ - request_body = self.__handle_parameters(locals()) + request_body = self._handle_parameters(locals()) return self.api.request( "POST", ( @@ -50,7 +45,7 @@ def getGroupData(self, groupId: str) -> Response: https://green-api.com/en/docs/api/groups/GetGroupData/ """ - request_body = self.__handle_parameters(locals()) + request_body = self._handle_parameters(locals()) return self.api.request( "POST", ( @@ -68,7 +63,7 @@ def addGroupParticipant( https://green-api.com/en/docs/api/groups/AddGroupParticipant/ """ - request_body = self.__handle_parameters(locals()) + request_body = self._handle_parameters(locals()) return self.api.request( "POST", ( @@ -86,7 +81,7 @@ def removeGroupParticipant( https://green-api.com/en/docs/api/groups/RemoveGroupParticipant/ """ - request_body = self.__handle_parameters(locals()) + request_body = self._handle_parameters(locals()) return self.api.request( "POST", ( @@ -102,7 +97,7 @@ def setGroupAdmin(self, groupId: str, participantChatId: str) -> Response: https://green-api.com/en/docs/api/groups/SetGroupAdmin/ """ - request_body = self.__handle_parameters(locals()) + request_body = self._handle_parameters(locals()) return self.api.request( "POST", ( @@ -119,7 +114,7 @@ def removeAdmin(self, groupId: str, participantChatId: str) -> Response: https://green-api.com/en/docs/api/groups/RemoveAdmin/ """ - request_body = self.__handle_parameters(locals()) + request_body = self._handle_parameters(locals()) return self.api.request( "POST", ( @@ -135,7 +130,7 @@ def setGroupPicture(self, groupId: str, path: str) -> Response: https://green-api.com/en/docs/api/groups/SetGroupPicture/ """ - request_body = self.__handle_parameters(locals()) + request_body = self._handle_parameters(locals()) file_name = Path(path).name files = {"file": (file_name, open(path, "rb"), "image/jpeg")} @@ -156,7 +151,7 @@ def leaveGroup(self, groupId: str) -> Response: https://green-api.com/en/docs/api/groups/LeaveGroup/ """ - request_body = self.__handle_parameters(locals()) + request_body = self._handle_parameters(locals()) return self.api.request( "POST", ( @@ -165,14 +160,5 @@ def leaveGroup(self, groupId: str) -> Response: ), request_body ) - @classmethod - def __handle_parameters(cls, parameters: dict) -> dict: - handled_parameters = parameters.copy() - - handled_parameters.pop("self") - - for key, value in parameters.items(): - if value is None: - handled_parameters.pop(key) - return handled_parameters +__all__ = ["Groups"] diff --git a/whatsapp_api_client_python/tools/journals.py b/whatsapp_api_client_python/tools/journals.py index 81d98fd..6d02f17 100644 --- a/whatsapp_api_client_python/tools/journals.py +++ b/whatsapp_api_client_python/tools/journals.py @@ -1,15 +1,10 @@ -from typing import Optional, TYPE_CHECKING +from typing import Optional +from .base import BaseCategory from ..response import Response -if TYPE_CHECKING: - from ..API import GreenApi - - -class Journals: - def __init__(self, api: "GreenApi"): - self.api = api +class Journals(BaseCategory): def getChatHistory( self, chatId: str, count: Optional[int] = None ) -> Response: @@ -83,3 +78,6 @@ def lastOutgoingMessages(self, minutes: Optional[int] = None) -> Response: "lastOutgoingMessages/{{apiTokenInstance}}" ), request_body ) + + +__all__ = ["Journals"] diff --git a/whatsapp_api_client_python/tools/marking.py b/whatsapp_api_client_python/tools/marking.py index 70f2193..5c76072 100644 --- a/whatsapp_api_client_python/tools/marking.py +++ b/whatsapp_api_client_python/tools/marking.py @@ -1,15 +1,10 @@ -from typing import Optional, TYPE_CHECKING +from typing import Optional +from .base import BaseCategory from ..response import Response -if TYPE_CHECKING: - from ..API import GreenApi - - -class Marking: - def __init__(self, api: "GreenApi"): - self.api = api +class Marking(BaseCategory): def readChat( self, chatId: str, idMessage: Optional[str] = None ) -> Response: @@ -30,3 +25,6 @@ def readChat( "readChat/{{apiTokenInstance}}" ), request_body ) + + +__all__ = ["Marking"] diff --git a/whatsapp_api_client_python/tools/queues.py b/whatsapp_api_client_python/tools/queues.py index 60684ba..54e671b 100644 --- a/whatsapp_api_client_python/tools/queues.py +++ b/whatsapp_api_client_python/tools/queues.py @@ -1,15 +1,8 @@ -from typing import TYPE_CHECKING - +from .base import BaseCategory from ..response import Response -if TYPE_CHECKING: - from ..API import GreenApi - - -class Queues: - def __init__(self, api: "GreenApi"): - self.api = api +class Queues(BaseCategory): def showMessagesQueue(self) -> Response: """ The method is aimed for getting a list of messages in the queue @@ -39,3 +32,6 @@ def clearMessagesQueue(self) -> Response: "clearMessagesQueue/{{apiTokenInstance}}" ) ) + + +__all__ = ["Queues"] diff --git a/whatsapp_api_client_python/tools/receiving.py b/whatsapp_api_client_python/tools/receiving.py index 8c3964a..47ff126 100644 --- a/whatsapp_api_client_python/tools/receiving.py +++ b/whatsapp_api_client_python/tools/receiving.py @@ -1,15 +1,8 @@ -from typing import TYPE_CHECKING - +from .base import BaseCategory from ..response import Response -if TYPE_CHECKING: - from ..API import GreenApi - - -class Receiving: - def __init__(self, api: "GreenApi"): - self.api = api +class Receiving(BaseCategory): def receiveNotification(self) -> Response: """ The method is aimed for receiving one incoming notification @@ -56,3 +49,6 @@ def downloadFile(self, chatId: str, idMessage: str) -> Response: "downloadFile/{{apiTokenInstance}}" ), request_body ) + + +__all__ = ["Receiving"] diff --git a/whatsapp_api_client_python/tools/sending.py b/whatsapp_api_client_python/tools/sending.py index f9de6c6..8350179 100644 --- a/whatsapp_api_client_python/tools/sending.py +++ b/whatsapp_api_client_python/tools/sending.py @@ -1,17 +1,12 @@ import mimetypes import pathlib -from typing import Dict, List, Optional, TYPE_CHECKING, Union +from typing import Dict, List, Optional, Union +from .base import BaseCategory from ..response import Response -if TYPE_CHECKING: - from ..API import GreenApi - - -class Sending: - def __init__(self, api: "GreenApi"): - self.api = api +class Sending(BaseCategory): def sendMessage( self, chatId: str, @@ -27,7 +22,7 @@ def sendMessage( https://green-api.com/en/docs/api/sending/SendMessage/ """ - request_body = self.__handle_parameters(locals()) + request_body = self._handle_parameters(locals()) return self.api.request( "POST", ( @@ -52,7 +47,7 @@ def sendButtons( https://green-api.com/en/docs/api/sending/SendButtons/ """ - request_body = self.__handle_parameters(locals()) + request_body = self._handle_parameters(locals()) return self.api.request( "POST", ( @@ -77,7 +72,7 @@ def sendTemplateButtons( https://green-api.com/en/docs/api/sending/SendTemplateButtons/ """ - request_body = self.__handle_parameters(locals()) + request_body = self._handle_parameters(locals()) return self.api.request( "POST", ( @@ -104,7 +99,7 @@ def sendListMessage( https://green-api.com/en/docs/api/sending/SendListMessage/ """ - request_body = self.__handle_parameters(locals()) + request_body = self._handle_parameters(locals()) return self.api.request( "POST", ( @@ -128,7 +123,7 @@ def sendFileByUpload( https://green-api.com/en/docs/api/sending/SendFileByUpload/ """ - request_body = self.__handle_parameters(locals()) + request_body = self._handle_parameters(locals()) file_name = pathlib.Path(path).name content_type = mimetypes.guess_type(file_name)[0] @@ -159,7 +154,7 @@ def sendFileByUrl( https://green-api.com/en/docs/api/sending/SendFileByUrl/ """ - request_body = self.__handle_parameters(locals()) + request_body = self._handle_parameters(locals()) return self.api.request( "POST", ( @@ -205,7 +200,7 @@ def sendLocation( https://green-api.com/en/docs/api/sending/SendLocation/ """ - request_body = self.__handle_parameters(locals()) + request_body = self._handle_parameters(locals()) return self.api.request( "POST", ( @@ -226,7 +221,7 @@ def sendContact( https://green-api.com/en/docs/api/sending/SendContact/ """ - request_body = self.__handle_parameters(locals()) + request_body = self._handle_parameters(locals()) return self.api.request( "POST", ( @@ -250,7 +245,7 @@ def sendLink( https://green-api.com/en/docs/api/sending/SendLink/ """ - request_body = self.__handle_parameters(locals()) + request_body = self._handle_parameters(locals()) return self.api.request( "POST", ( @@ -272,7 +267,7 @@ def forwardMessages( https://green-api.com/en/docs/api/sending/ForwardMessages/ """ - request_body = self.__handle_parameters(locals()) + request_body = self._handle_parameters(locals()) return self.api.request( "POST", ( @@ -296,7 +291,7 @@ def sendPoll( https://green-api.com/en/docs/api/sending/SendPoll/ """ - request_body = self.__handle_parameters(locals()) + request_body = self._handle_parameters(locals()) return self.api.request( "POST", ( @@ -305,14 +300,5 @@ def sendPoll( ), request_body ) - @classmethod - def __handle_parameters(cls, parameters: dict) -> dict: - handled_parameters = parameters.copy() - - handled_parameters.pop("self") - - for key, value in parameters.items(): - if value is None: - handled_parameters.pop(key) - return handled_parameters +__all__ = ["Sending"] diff --git a/whatsapp_api_client_python/tools/serviceMethods.py b/whatsapp_api_client_python/tools/serviceMethods.py index 1ceab7f..228665b 100644 --- a/whatsapp_api_client_python/tools/serviceMethods.py +++ b/whatsapp_api_client_python/tools/serviceMethods.py @@ -1,15 +1,10 @@ -from typing import Optional, TYPE_CHECKING +from typing import Optional +from .base import BaseCategory from ..response import Response -if TYPE_CHECKING: - from ..API import GreenApi - - -class ServiceMethods: - def __init__(self, api: "GreenApi"): - self.api = api +class ServiceMethods(BaseCategory): def checkWhatsapp(self, phoneNumber: int) -> Response: """ The method checks WhatsApp account availability on a phone @@ -149,3 +144,6 @@ def setDisappearingChat( "setDisappearingChat/{{apiTokenInstance}}" ), request_body ) + + +__all__ = ["ServiceMethods"]