pygwan 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pygwan-0.1.0/LICENSE +19 -0
- pygwan-0.1.0/PKG-INFO +87 -0
- pygwan-0.1.0/README.md +74 -0
- pygwan-0.1.0/pyproject.toml +19 -0
- pygwan-0.1.0/src/pygwan/__init__.py +0 -0
- pygwan-0.1.0/src/pygwan/pygwan.py +1063 -0
pygwan-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Copyright (c) 2018 The Python Packaging Authority
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
5
|
+
in the Software without restriction, including without limitation the rights
|
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
8
|
+
furnished to do so, subject to the following conditions:
|
|
9
|
+
|
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
|
11
|
+
copies or substantial portions of the Software.
|
|
12
|
+
|
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
19
|
+
SOFTWARE.
|
pygwan-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: pygwan
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Unofficial Python wrapper for the WhatsApp Cloud API by Tarmica Chiwara
|
|
5
|
+
Project-URL: Homepage, https://github.com/yourusername/pygwan
|
|
6
|
+
Author-email: Tarmica Chiwara <tarimicac@gmail.com>
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Requires-Python: >=3.7
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
|
|
14
|
+
# Pygwan
|
|
15
|
+
|
|
16
|
+
Unofficial Python wrapper for the WhatsApp Cloud API by Tarmica Chiwara.
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
To install the WhatsApp Python wrapper, use the following command:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pip install pygwan
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Usage
|
|
27
|
+
|
|
28
|
+
Import the `WhatsApp` class from the package and initialize an instance with your WhatsApp token and phone number ID:
|
|
29
|
+
|
|
30
|
+
```python
|
|
31
|
+
from pygwan import WhatsApp
|
|
32
|
+
|
|
33
|
+
whatsapp = WhatsApp(token="your_token", phone_number_id="your_phone_number_id")
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Sending a Message
|
|
37
|
+
|
|
38
|
+
You can send a text message to a WhatsApp user using the `send_message` method:
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
whatsapp.send_message("Hello, this is a test message.", "recipient_phone_number")
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Replying to a Message
|
|
45
|
+
|
|
46
|
+
Reply to a message using the `reply_to_message` method:
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
whatsapp.reply_to_message("message_id", "recipient_phone_number", "Reply message.")
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Sending a Template
|
|
53
|
+
|
|
54
|
+
Send a template message using the `send_template` method:
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
components = [
|
|
58
|
+
# List of template components
|
|
59
|
+
# Example: {"type": "text", "text": "Hello, this is a template message."}
|
|
60
|
+
]
|
|
61
|
+
whatsapp.send_template("template_name", "recipient_phone_number", components)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Sending a Location
|
|
65
|
+
|
|
66
|
+
Send a location message using the `send_location` method:
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
whatsapp.send_location("-23.564", "-46.654", "Location Name", "Location Address", "recipient_phone_number")
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Sending an Image
|
|
73
|
+
|
|
74
|
+
Send an image message using the `send_image` method:
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
image_link = "https://example.com/image.jpg"
|
|
78
|
+
whatsapp.send_image(image_link, "recipient_phone_number")
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Documentation
|
|
82
|
+
|
|
83
|
+
For more detailed usage and information, please refer to the official documentation in the code lol
|
|
84
|
+
|
|
85
|
+
## License
|
|
86
|
+
|
|
87
|
+
This project is licensed under the [MIT License](https://opensource.org/licenses/MIT).
|
pygwan-0.1.0/README.md
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Pygwan
|
|
2
|
+
|
|
3
|
+
Unofficial Python wrapper for the WhatsApp Cloud API by Tarmica Chiwara.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
To install the WhatsApp Python wrapper, use the following command:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install pygwan
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
Import the `WhatsApp` class from the package and initialize an instance with your WhatsApp token and phone number ID:
|
|
16
|
+
|
|
17
|
+
```python
|
|
18
|
+
from pygwan import WhatsApp
|
|
19
|
+
|
|
20
|
+
whatsapp = WhatsApp(token="your_token", phone_number_id="your_phone_number_id")
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Sending a Message
|
|
24
|
+
|
|
25
|
+
You can send a text message to a WhatsApp user using the `send_message` method:
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
whatsapp.send_message("Hello, this is a test message.", "recipient_phone_number")
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Replying to a Message
|
|
32
|
+
|
|
33
|
+
Reply to a message using the `reply_to_message` method:
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
whatsapp.reply_to_message("message_id", "recipient_phone_number", "Reply message.")
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Sending a Template
|
|
40
|
+
|
|
41
|
+
Send a template message using the `send_template` method:
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
components = [
|
|
45
|
+
# List of template components
|
|
46
|
+
# Example: {"type": "text", "text": "Hello, this is a template message."}
|
|
47
|
+
]
|
|
48
|
+
whatsapp.send_template("template_name", "recipient_phone_number", components)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Sending a Location
|
|
52
|
+
|
|
53
|
+
Send a location message using the `send_location` method:
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
whatsapp.send_location("-23.564", "-46.654", "Location Name", "Location Address", "recipient_phone_number")
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Sending an Image
|
|
60
|
+
|
|
61
|
+
Send an image message using the `send_image` method:
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
image_link = "https://example.com/image.jpg"
|
|
65
|
+
whatsapp.send_image(image_link, "recipient_phone_number")
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Documentation
|
|
69
|
+
|
|
70
|
+
For more detailed usage and information, please refer to the official documentation in the code lol
|
|
71
|
+
|
|
72
|
+
## License
|
|
73
|
+
|
|
74
|
+
This project is licensed under the [MIT License](https://opensource.org/licenses/MIT).
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "pygwan"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
authors = [{ name = "Tarmica Chiwara", email = "tarimicac@gmail.com" }]
|
|
9
|
+
description = "Unofficial Python wrapper for the WhatsApp Cloud API by Tarmica Chiwara"
|
|
10
|
+
readme = "README.md"
|
|
11
|
+
requires-python = ">=3.7"
|
|
12
|
+
classifiers = [
|
|
13
|
+
"Programming Language :: Python :: 3",
|
|
14
|
+
"License :: OSI Approved :: MIT License",
|
|
15
|
+
"Operating System :: OS Independent",
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
[project.urls]
|
|
19
|
+
Homepage = "https://github.com/yourusername/pygwan"
|
|
File without changes
|
|
@@ -0,0 +1,1063 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Unofficial python wrapper for the WhatsApp Cloud API by Tarmica Chiwara
|
|
3
|
+
"""
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
import os
|
|
6
|
+
import mimetypes
|
|
7
|
+
import requests
|
|
8
|
+
import logging
|
|
9
|
+
import warnings
|
|
10
|
+
from colorama import Fore, Style
|
|
11
|
+
from requests_toolbelt.multipart.encoder import MultipartEncoder
|
|
12
|
+
from typing import Optional, Dict, Any, List, Union, Tuple, Callable
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# Setup logging
|
|
16
|
+
logging.getLogger(__name__).addHandler(logging.NullHandler())
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class WhatsApp(object):
|
|
20
|
+
""" "
|
|
21
|
+
WhatsApp Object
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
def __init__(self, token=None, phone_number_id=None):
|
|
25
|
+
"""
|
|
26
|
+
Initialize the WhatsApp Object
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
token[str]: Token for the WhatsApp cloud API obtained from the developer portal
|
|
30
|
+
phone_number_id[str]: Phone number id for the WhatsApp cloud API obtained from the developer portal
|
|
31
|
+
"""
|
|
32
|
+
self.token = token
|
|
33
|
+
self.phone_number_id = phone_number_id
|
|
34
|
+
self.base_url = "https://graph.facebook.com/v17.0"
|
|
35
|
+
self.v15_base_url = "https://graph.facebook.com/v17.0"
|
|
36
|
+
self.url = f"{self.base_url}/{phone_number_id}/messages"
|
|
37
|
+
|
|
38
|
+
self.headers = {
|
|
39
|
+
"Content-Type": "application/json",
|
|
40
|
+
"Authorization": "Bearer {}".format(self.token),
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
def send_message(
|
|
44
|
+
self, message, recipient_id, recipient_type="individual", preview_url=True
|
|
45
|
+
):
|
|
46
|
+
"""
|
|
47
|
+
Sends a text message to a WhatsApp user
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
message[str]: Message to be sent to the user
|
|
51
|
+
recipient_id[str]: Phone number of the user with country code wihout +
|
|
52
|
+
recipient_type[str]: Type of the recipient, either individual or group
|
|
53
|
+
preview_url[bool]: Whether to send a preview url or not
|
|
54
|
+
|
|
55
|
+
Example:
|
|
56
|
+
```python
|
|
57
|
+
>>> from whatsapp import WhatsApp
|
|
58
|
+
>>> whatsapp = WhatsApp(token, phone_number_id)
|
|
59
|
+
>>> whatsapp.send_message("Hello World", "5511999999999")
|
|
60
|
+
>>> whatsapp.send_message("Hello World", "5511999999999", preview_url=False)
|
|
61
|
+
|
|
62
|
+
"""
|
|
63
|
+
data = {
|
|
64
|
+
"messaging_product": "whatsapp",
|
|
65
|
+
"recipient_type": recipient_type,
|
|
66
|
+
"to": recipient_id,
|
|
67
|
+
"type": "text",
|
|
68
|
+
"text": {"preview_url": preview_url, "body": message},
|
|
69
|
+
}
|
|
70
|
+
logging.info(f"Sending message to {recipient_id}")
|
|
71
|
+
r = requests.post(f"{self.url}", headers=self.headers, json=data)
|
|
72
|
+
if r.status_code == 200:
|
|
73
|
+
logging.info(f"Message sent to {recipient_id}")
|
|
74
|
+
return r.json()
|
|
75
|
+
logging.info(f"Message not sent to {recipient_id}")
|
|
76
|
+
logging.info(f"Status code: {r.status_code}")
|
|
77
|
+
logging.error(f"Response: {r.json()}")
|
|
78
|
+
return r.json()
|
|
79
|
+
|
|
80
|
+
def reply_to_message(
|
|
81
|
+
self, message_id: str, recipient_id: str, message: str, preview_url: bool = True
|
|
82
|
+
):
|
|
83
|
+
"""
|
|
84
|
+
Replies to a message
|
|
85
|
+
|
|
86
|
+
Args:
|
|
87
|
+
message_id[str]: Message id of the message to be replied to
|
|
88
|
+
recipient_id[str]: Phone number of the user with country code wihout +
|
|
89
|
+
message[str]: Message to be sent to the user
|
|
90
|
+
preview_url[bool]: Whether to send a preview url or not
|
|
91
|
+
"""
|
|
92
|
+
data = {
|
|
93
|
+
"messaging_product": "whatsapp",
|
|
94
|
+
"recipient_type": "individual",
|
|
95
|
+
"to": recipient_id,
|
|
96
|
+
"type": "text",
|
|
97
|
+
"context": {"message_id": message_id},
|
|
98
|
+
"text": {"preview_url": preview_url, "body": message},
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
logging.info(f"Replying to {message_id}")
|
|
102
|
+
r = requests.post(f"{self.url}", headers=self.headers, json=data)
|
|
103
|
+
if r.status_code == 200:
|
|
104
|
+
logging.info(f"Message sent to {recipient_id}")
|
|
105
|
+
return r.json()
|
|
106
|
+
logging.info(f"Message not sent to {recipient_id}")
|
|
107
|
+
logging.info(f"Status code: {r.status_code}")
|
|
108
|
+
logging.error(f"Response: {r.json()}")
|
|
109
|
+
return r.json()
|
|
110
|
+
|
|
111
|
+
def send_template(self, template, recipient_id, components, lang: str = "en_US"):
|
|
112
|
+
"""
|
|
113
|
+
Sends a template message to a WhatsApp user, Template messages can either be;
|
|
114
|
+
1. Text template
|
|
115
|
+
2. Media based template
|
|
116
|
+
3. Interactive template
|
|
117
|
+
You can customize the template message by passing a dictionary of components.
|
|
118
|
+
You can find the available components in the documentation.
|
|
119
|
+
https://developers.facebook.com/docs/whatsapp/cloud-api/guides/send-message-templates
|
|
120
|
+
Args:
|
|
121
|
+
template[str]: Template name to be sent to the user
|
|
122
|
+
recipient_id[str]: Phone number of the user with country code wihout +
|
|
123
|
+
lang[str]: Language of the template message
|
|
124
|
+
components[list]: List of components to be sent to the user # CHANGE
|
|
125
|
+
Example:
|
|
126
|
+
>>> from whatsapp import WhatsApp
|
|
127
|
+
>>> whatsapp = WhatsApp(token, phone_number_id)
|
|
128
|
+
>>> whatsapp.send_template("hello_world", "5511999999999", lang="en_US"))
|
|
129
|
+
"""
|
|
130
|
+
data = {
|
|
131
|
+
"messaging_product": "whatsapp",
|
|
132
|
+
"to": recipient_id,
|
|
133
|
+
"type": "template",
|
|
134
|
+
"template": {
|
|
135
|
+
"name": template,
|
|
136
|
+
"language": {"code": lang},
|
|
137
|
+
"components": components,
|
|
138
|
+
},
|
|
139
|
+
}
|
|
140
|
+
logging.info(f"Sending template to {recipient_id}")
|
|
141
|
+
r = requests.post(self.url, headers=self.headers, json=data)
|
|
142
|
+
if r.status_code == 200:
|
|
143
|
+
logging.info(f"Template sent to {recipient_id}")
|
|
144
|
+
return r.json()
|
|
145
|
+
logging.info(f"Template not sent to {recipient_id}")
|
|
146
|
+
logging.info(f"Status code: {r.status_code}")
|
|
147
|
+
logging.error(f"Response: {r.json()}")
|
|
148
|
+
return r.json()
|
|
149
|
+
|
|
150
|
+
def send_templatev2(self, template, recipient_id, components, lang: str = "en_US"):
|
|
151
|
+
message = f"{Fore.RED}The 'send_templatev2' method is being deprecated and will be removed in the future. Please use the 'send_template' method instead.{Style.RESET_ALL}"
|
|
152
|
+
warnings.warn(message, DeprecationWarning)
|
|
153
|
+
return send_template(template, recipient_id, components, lang=lang) # type: ignore
|
|
154
|
+
|
|
155
|
+
def send_location(self, lat, long, name, address, recipient_id):
|
|
156
|
+
"""
|
|
157
|
+
Sends a location message to a WhatsApp user
|
|
158
|
+
|
|
159
|
+
Args:
|
|
160
|
+
lat[str]: Latitude of the location
|
|
161
|
+
long[str]: Longitude of the location
|
|
162
|
+
name[str]: Name of the location
|
|
163
|
+
address[str]: Address of the location
|
|
164
|
+
recipient_id[str]: Phone number of the user with country code wihout +
|
|
165
|
+
|
|
166
|
+
Example:
|
|
167
|
+
>>> from whatsapp import WhatsApp
|
|
168
|
+
>>> whatsapp = WhatsApp(token, phone_number_id)
|
|
169
|
+
>>> whatsapp.send_location("-23.564", "-46.654", "My Location", "Rua dois, 123", "5511999999999")
|
|
170
|
+
"""
|
|
171
|
+
data = {
|
|
172
|
+
"messaging_product": "whatsapp",
|
|
173
|
+
"to": recipient_id,
|
|
174
|
+
"type": "location",
|
|
175
|
+
"location": {
|
|
176
|
+
"latitude": lat,
|
|
177
|
+
"longitude": long,
|
|
178
|
+
"name": name,
|
|
179
|
+
"address": address,
|
|
180
|
+
},
|
|
181
|
+
}
|
|
182
|
+
logging.info(f"Sending location to {recipient_id}")
|
|
183
|
+
r = requests.post(self.url, headers=self.headers, json=data)
|
|
184
|
+
if r.status_code == 200:
|
|
185
|
+
logging.info(f"Location sent to {recipient_id}")
|
|
186
|
+
return r.json()
|
|
187
|
+
logging.info(f"Location not sent to {recipient_id}")
|
|
188
|
+
logging.info(f"Status code: {r.status_code}")
|
|
189
|
+
logging.error(r.json())
|
|
190
|
+
return r.json()
|
|
191
|
+
|
|
192
|
+
def send_image(
|
|
193
|
+
self,
|
|
194
|
+
image,
|
|
195
|
+
recipient_id,
|
|
196
|
+
recipient_type="individual",
|
|
197
|
+
caption=None,
|
|
198
|
+
link=True,
|
|
199
|
+
):
|
|
200
|
+
"""
|
|
201
|
+
Sends an image message to a WhatsApp user
|
|
202
|
+
|
|
203
|
+
There are two ways to send an image message to a user, either by passing the image id or by passing the image link.
|
|
204
|
+
Image id is the id of the image uploaded to the cloud api.
|
|
205
|
+
|
|
206
|
+
Args:
|
|
207
|
+
image[str]: Image id or link of the image
|
|
208
|
+
recipient_id[str]: Phone number of the user with country code wihout +
|
|
209
|
+
recipient_type[str]: Type of the recipient, either individual or group
|
|
210
|
+
caption[str]: Caption of the image
|
|
211
|
+
link[bool]: Whether to send an image id or an image link, True means that the image is an id, False means that the image is a link
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
Example:
|
|
215
|
+
>>> from whatsapp import WhatsApp
|
|
216
|
+
>>> whatsapp = WhatsApp(token, phone_number_id)
|
|
217
|
+
>>> whatsapp.send_image("https://i.imgur.com/Fh7XVYY.jpeg", "5511999999999")
|
|
218
|
+
"""
|
|
219
|
+
if link:
|
|
220
|
+
data = {
|
|
221
|
+
"messaging_product": "whatsapp",
|
|
222
|
+
"recipient_type": recipient_type,
|
|
223
|
+
"to": recipient_id,
|
|
224
|
+
"type": "image",
|
|
225
|
+
"image": {"link": image, "caption": caption},
|
|
226
|
+
}
|
|
227
|
+
else:
|
|
228
|
+
data = {
|
|
229
|
+
"messaging_product": "whatsapp",
|
|
230
|
+
"recipient_type": recipient_type,
|
|
231
|
+
"to": recipient_id,
|
|
232
|
+
"type": "image",
|
|
233
|
+
"image": {"id": image, "caption": caption},
|
|
234
|
+
}
|
|
235
|
+
logging.info(f"Sending image to {recipient_id}")
|
|
236
|
+
r = requests.post(self.url, headers=self.headers, json=data)
|
|
237
|
+
if r.status_code == 200:
|
|
238
|
+
logging.info(f"Image sent to {recipient_id}")
|
|
239
|
+
return r.json()
|
|
240
|
+
logging.info(f"Image not sent to {recipient_id}")
|
|
241
|
+
logging.info(f"Status code: {r.status_code}")
|
|
242
|
+
logging.error(r.json())
|
|
243
|
+
return r.json()
|
|
244
|
+
|
|
245
|
+
def send_sticker(
|
|
246
|
+
self, sticker: str, recipient_id: str, recipient_type="individual", link=True
|
|
247
|
+
):
|
|
248
|
+
"""
|
|
249
|
+
Sends a sticker message to a WhatsApp user
|
|
250
|
+
|
|
251
|
+
There are two ways to send a sticker message to a user, either by passing the image id or by passing the sticker link.
|
|
252
|
+
Sticker id is the id of the sticker uploaded to the cloud api.
|
|
253
|
+
|
|
254
|
+
Args:
|
|
255
|
+
sticker[str]: Sticker id or link of the sticker
|
|
256
|
+
recipient_id[str]: Phone number of the user with country code wihout +
|
|
257
|
+
recipient_type[str]: Type of the recipient, either individual or group
|
|
258
|
+
link[bool]: Whether to send an sticker id or an sticker link, True means that the sticker is an id, False means that the image is a link
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
Example:
|
|
262
|
+
>>> from whatsapp import WhatsApp
|
|
263
|
+
>>> whatsapp = WhatsApp(token, phone_number_id)
|
|
264
|
+
>>> whatsapp.send_sticker("170511049062862", "5511999999999", link=False)
|
|
265
|
+
"""
|
|
266
|
+
if link:
|
|
267
|
+
data = {
|
|
268
|
+
"messaging_product": "whatsapp",
|
|
269
|
+
"recipient_type": recipient_type,
|
|
270
|
+
"to": recipient_id,
|
|
271
|
+
"type": "sticker",
|
|
272
|
+
"sticker": {"link": sticker},
|
|
273
|
+
}
|
|
274
|
+
else:
|
|
275
|
+
data = {
|
|
276
|
+
"messaging_product": "whatsapp",
|
|
277
|
+
"recipient_type": recipient_type,
|
|
278
|
+
"to": recipient_id,
|
|
279
|
+
"type": "sticker",
|
|
280
|
+
"sticker": {"id": sticker},
|
|
281
|
+
}
|
|
282
|
+
logging.info(f"Sending sticker to {recipient_id}")
|
|
283
|
+
r = requests.post(self.url, headers=self.headers, json=data)
|
|
284
|
+
if r.status_code == 200:
|
|
285
|
+
logging.info(f"Sticker sent to {recipient_id}")
|
|
286
|
+
return r.json()
|
|
287
|
+
logging.info(f"Sticker not sent to {recipient_id}")
|
|
288
|
+
logging.info(f"Status code: {r.status_code}")
|
|
289
|
+
logging.error(r.json())
|
|
290
|
+
return r.json()
|
|
291
|
+
|
|
292
|
+
def send_audio(self, audio, recipient_id, link=True):
|
|
293
|
+
"""
|
|
294
|
+
Sends an audio message to a WhatsApp user
|
|
295
|
+
Audio messages can either be sent by passing the audio id or by passing the audio link.
|
|
296
|
+
|
|
297
|
+
Args:
|
|
298
|
+
audio[str]: Audio id or link of the audio
|
|
299
|
+
recipient_id[str]: Phone number of the user with country code wihout +
|
|
300
|
+
link[bool]: Whether to send an audio id or an audio link, True means that the audio is an id, False means that the audio is a link
|
|
301
|
+
|
|
302
|
+
Example:
|
|
303
|
+
>>> from whatsapp import WhatsApp
|
|
304
|
+
>>> whatsapp = WhatsApp(token, phone_number_id)
|
|
305
|
+
>>> whatsapp.send_audio("https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3", "5511999999999")
|
|
306
|
+
"""
|
|
307
|
+
if link:
|
|
308
|
+
data = {
|
|
309
|
+
"messaging_product": "whatsapp",
|
|
310
|
+
"to": recipient_id,
|
|
311
|
+
"type": "audio",
|
|
312
|
+
"audio": {"link": audio},
|
|
313
|
+
}
|
|
314
|
+
else:
|
|
315
|
+
data = {
|
|
316
|
+
"messaging_product": "whatsapp",
|
|
317
|
+
"to": recipient_id,
|
|
318
|
+
"type": "audio",
|
|
319
|
+
"audio": {"id": audio},
|
|
320
|
+
}
|
|
321
|
+
logging.info(f"Sending audio to {recipient_id}")
|
|
322
|
+
r = requests.post(self.url, headers=self.headers, json=data)
|
|
323
|
+
if r.status_code == 200:
|
|
324
|
+
logging.info(f"Audio sent to {recipient_id}")
|
|
325
|
+
return r.json()
|
|
326
|
+
logging.info(f"Audio not sent to {recipient_id}")
|
|
327
|
+
logging.info(f"Status code: {r.status_code}")
|
|
328
|
+
logging.error(f"Response: {r.json()}")
|
|
329
|
+
return r.json()
|
|
330
|
+
|
|
331
|
+
def send_video(
|
|
332
|
+
self, video, recipient_id, caption=None, link=True
|
|
333
|
+
) -> Dict[Any, Any]:
|
|
334
|
+
""" "
|
|
335
|
+
Sends a video message to a WhatsApp user
|
|
336
|
+
Video messages can either be sent by passing the video id or by passing the video link.
|
|
337
|
+
|
|
338
|
+
Args:
|
|
339
|
+
video[str]: Video id or link of the video
|
|
340
|
+
recipient_id[str]: Phone number of the user with country code wihout +
|
|
341
|
+
caption[str]: Caption of the video
|
|
342
|
+
link[bool]: Whether to send a video id or a video link, True means that the video is an id, False means that the video is a link
|
|
343
|
+
|
|
344
|
+
example:
|
|
345
|
+
>>> from whatsapp import WhatsApp
|
|
346
|
+
>>> whatsapp = WhatsApp(token, phone_number_id)
|
|
347
|
+
>>> whatsapp.send_video("https://www.youtube.com/watch?v=dQw4w9WgXcQ", "5511999999999")
|
|
348
|
+
"""
|
|
349
|
+
if link:
|
|
350
|
+
data = {
|
|
351
|
+
"messaging_product": "whatsapp",
|
|
352
|
+
"to": recipient_id,
|
|
353
|
+
"type": "video",
|
|
354
|
+
"video": {"link": video, "caption": caption},
|
|
355
|
+
}
|
|
356
|
+
else:
|
|
357
|
+
data = {
|
|
358
|
+
"messaging_product": "whatsapp",
|
|
359
|
+
"to": recipient_id,
|
|
360
|
+
"type": "video",
|
|
361
|
+
"video": {"id": video, "caption": caption},
|
|
362
|
+
}
|
|
363
|
+
logging.info(f"Sending video to {recipient_id}")
|
|
364
|
+
r = requests.post(self.url, headers=self.headers, json=data)
|
|
365
|
+
if r.status_code == 200:
|
|
366
|
+
logging.info(f"Video sent to {recipient_id}")
|
|
367
|
+
return r.json()
|
|
368
|
+
logging.info(f"Video not sent to {recipient_id}")
|
|
369
|
+
logging.info(f"Status code: {r.status_code}")
|
|
370
|
+
logging.error(f"Response: {r.json()}")
|
|
371
|
+
return r.json()
|
|
372
|
+
|
|
373
|
+
def send_custom_json(self, data, recipient_id=None):
|
|
374
|
+
"""
|
|
375
|
+
Sends a custom json to a WhatsApp user. This can be used to send custom objects to the message endpoint.
|
|
376
|
+
|
|
377
|
+
Args:
|
|
378
|
+
data[dict]: Dictionary that should be send
|
|
379
|
+
recipient_id[str]: Phone number of the user with country code wihout +
|
|
380
|
+
Example:
|
|
381
|
+
>>> from whatsapp import WhatsApp
|
|
382
|
+
>>> whatsapp = WhatsApp(token, phone_number_id)
|
|
383
|
+
>>> whatsapp.send_custom_json({
|
|
384
|
+
"messaging_product": "whatsapp",
|
|
385
|
+
"type": "audio",
|
|
386
|
+
"audio": {"id": audio}}, "5511999999999")
|
|
387
|
+
"""
|
|
388
|
+
|
|
389
|
+
if recipient_id:
|
|
390
|
+
if "to" in data.keys():
|
|
391
|
+
data_recipient_id = data["to"]
|
|
392
|
+
logging.info(
|
|
393
|
+
f"Recipient Id is defined in data ({data_recipient_id}) and recipient_id parameter ({recipient_id})"
|
|
394
|
+
)
|
|
395
|
+
else:
|
|
396
|
+
data["to"] = recipient_id
|
|
397
|
+
|
|
398
|
+
logging.info(f"Sending custom json to {recipient_id}")
|
|
399
|
+
r = requests.post(self.url, headers=self.headers, json=data)
|
|
400
|
+
if r.status_code == 200:
|
|
401
|
+
logging.info(f"Custom json sent to {recipient_id}")
|
|
402
|
+
return r.json()
|
|
403
|
+
logging.info(f"Custom json not sent to {recipient_id}")
|
|
404
|
+
logging.info(f"Status code: {r.status_code}")
|
|
405
|
+
logging.error(f"Response: {r.json()}")
|
|
406
|
+
return r.json()
|
|
407
|
+
|
|
408
|
+
def send_document(
|
|
409
|
+
self, document, recipient_id, caption=None, link=True
|
|
410
|
+
) -> Dict[Any, Any]:
|
|
411
|
+
""" "
|
|
412
|
+
Sends a document message to a WhatsApp user
|
|
413
|
+
Document messages can either be sent by passing the document id or by passing the document link.
|
|
414
|
+
|
|
415
|
+
Args:
|
|
416
|
+
document[str]: Document id or link of the document
|
|
417
|
+
recipient_id[str]: Phone number of the user with country code wihout +
|
|
418
|
+
caption[str]: Caption of the document
|
|
419
|
+
link[bool]: Whether to send a document id or a document link, True means that the document is an id, False means that the document is a link
|
|
420
|
+
|
|
421
|
+
Example:
|
|
422
|
+
>>> from whatsapp import WhatsApp
|
|
423
|
+
>>> whatsapp = WhatsApp(token, phone_number_id)
|
|
424
|
+
>>> whatsapp.send_document("https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf", "5511999999999")
|
|
425
|
+
"""
|
|
426
|
+
if link:
|
|
427
|
+
data = {
|
|
428
|
+
"messaging_product": "whatsapp",
|
|
429
|
+
"to": recipient_id,
|
|
430
|
+
"type": "document",
|
|
431
|
+
"document": {"link": document, "caption": caption},
|
|
432
|
+
}
|
|
433
|
+
else:
|
|
434
|
+
data = {
|
|
435
|
+
"messaging_product": "whatsapp",
|
|
436
|
+
"to": recipient_id,
|
|
437
|
+
"type": "document",
|
|
438
|
+
"document": {"id": document, "caption": caption},
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
logging.info(f"Sending document to {recipient_id}")
|
|
442
|
+
r = requests.post(self.url, headers=self.headers, json=data)
|
|
443
|
+
if r.status_code == 200:
|
|
444
|
+
logging.info(f"Document sent to {recipient_id}")
|
|
445
|
+
return r.json()
|
|
446
|
+
logging.info(f"Document not sent to {recipient_id}")
|
|
447
|
+
logging.info(f"Status code: {r.status_code}")
|
|
448
|
+
logging.error(f"Response: {r.json()}")
|
|
449
|
+
return r.json()
|
|
450
|
+
|
|
451
|
+
def send_contacts(
|
|
452
|
+
self, contacts: List[Dict[Any, Any]], recipient_id: str
|
|
453
|
+
) -> Dict[Any, Any]:
|
|
454
|
+
"""send_contacts
|
|
455
|
+
|
|
456
|
+
Send a list of contacts to a user
|
|
457
|
+
|
|
458
|
+
Args:
|
|
459
|
+
contacts(List[Dict[Any, Any]]): List of contacts to send
|
|
460
|
+
recipient_id(str): Phone number of the user with country code wihout +
|
|
461
|
+
|
|
462
|
+
Example:
|
|
463
|
+
>>> from whatsapp import WhatsApp
|
|
464
|
+
>>> whatsapp = WhatsApp(token, phone_number_id)
|
|
465
|
+
>>> contacts = [{
|
|
466
|
+
"addresses": [{
|
|
467
|
+
"street": "STREET",
|
|
468
|
+
"city": "CITY",
|
|
469
|
+
"state": "STATE",
|
|
470
|
+
"zip": "ZIP",
|
|
471
|
+
"country": "COUNTRY",
|
|
472
|
+
"country_code": "COUNTRY_CODE",
|
|
473
|
+
"type": "HOME"
|
|
474
|
+
},
|
|
475
|
+
....
|
|
476
|
+
}
|
|
477
|
+
]
|
|
478
|
+
|
|
479
|
+
REFERENCE: https://developers.facebook.com/docs/whatsapp/cloud-api/reference/messages#contacts-object
|
|
480
|
+
"""
|
|
481
|
+
|
|
482
|
+
data = {
|
|
483
|
+
"messaging_product": "whatsapp",
|
|
484
|
+
"to": recipient_id,
|
|
485
|
+
"type": "contacts",
|
|
486
|
+
"contacts": contacts,
|
|
487
|
+
}
|
|
488
|
+
logging.info(f"Sending contacts to {recipient_id}")
|
|
489
|
+
r = requests.post(self.url, headers=self.headers, json=data)
|
|
490
|
+
if r.status_code == 200:
|
|
491
|
+
logging.info(f"Contacts sent to {recipient_id}")
|
|
492
|
+
return r.json()
|
|
493
|
+
logging.info(f"Contacts not sent to {recipient_id}")
|
|
494
|
+
logging.info(f"Status code: {r.status_code}")
|
|
495
|
+
logging.error(f"Response: {r.json()}")
|
|
496
|
+
return r.json()
|
|
497
|
+
|
|
498
|
+
def upload_media(self, media: str) -> Union[Dict[Any, Any], None]:
|
|
499
|
+
"""
|
|
500
|
+
Uploads a media to the cloud api and returns the id of the media
|
|
501
|
+
|
|
502
|
+
Args:
|
|
503
|
+
media[str]: Path of the media to be uploaded
|
|
504
|
+
|
|
505
|
+
Example:
|
|
506
|
+
>>> from whatsapp import WhatsApp
|
|
507
|
+
>>> whatsapp = WhatsApp(token, phone_number_id)
|
|
508
|
+
>>> whatsapp.upload_media("/path/to/media")
|
|
509
|
+
|
|
510
|
+
REFERENCE: https://developers.facebook.com/docs/whatsapp/cloud-api/reference/media#
|
|
511
|
+
"""
|
|
512
|
+
form_data = {
|
|
513
|
+
"file": (
|
|
514
|
+
media,
|
|
515
|
+
open(os.path.realpath(media), "rb"),
|
|
516
|
+
mimetypes.guess_type(media)[0],
|
|
517
|
+
),
|
|
518
|
+
"messaging_product": "whatsapp",
|
|
519
|
+
"type": mimetypes.guess_type(media)[0],
|
|
520
|
+
}
|
|
521
|
+
form_data = MultipartEncoder(fields=form_data)
|
|
522
|
+
headers = self.headers.copy()
|
|
523
|
+
headers["Content-Type"] = form_data.content_type
|
|
524
|
+
logging.info(f"Content-Type: {form_data.content_type}")
|
|
525
|
+
logging.info(f"Uploading media {media}")
|
|
526
|
+
r = requests.post(
|
|
527
|
+
f"{self.base_url}/{self.phone_number_id}/media",
|
|
528
|
+
headers=headers,
|
|
529
|
+
data=form_data,
|
|
530
|
+
)
|
|
531
|
+
if r.status_code == 200:
|
|
532
|
+
logging.info(f"Media {media} uploaded")
|
|
533
|
+
return r.json()
|
|
534
|
+
logging.info(f"Error uploading media {media}")
|
|
535
|
+
logging.info(f"Status code: {r.status_code}")
|
|
536
|
+
logging.info(f"Response: {r.json()}")
|
|
537
|
+
return None
|
|
538
|
+
|
|
539
|
+
def delete_media(self, media_id: str) -> Union[Dict[Any, Any], None]:
|
|
540
|
+
"""
|
|
541
|
+
Deletes a media from the cloud api
|
|
542
|
+
|
|
543
|
+
Args:
|
|
544
|
+
media_id[str]: Id of the media to be deleted
|
|
545
|
+
"""
|
|
546
|
+
logging.info(f"Deleting media {media_id}")
|
|
547
|
+
r = requests.delete(f"{self.base_url}/{media_id}", headers=self.headers)
|
|
548
|
+
if r.status_code == 200:
|
|
549
|
+
logging.info(f"Media {media_id} deleted")
|
|
550
|
+
return r.json()
|
|
551
|
+
logging.info(f"Error deleting media {media_id}")
|
|
552
|
+
logging.info(f"Status code: {r.status_code}")
|
|
553
|
+
logging.info(f"Response: {r.json()}")
|
|
554
|
+
return None
|
|
555
|
+
|
|
556
|
+
def mark_as_read(self, message_id: str) -> Dict[Any, Any]:
|
|
557
|
+
"""
|
|
558
|
+
Marks a message as read
|
|
559
|
+
|
|
560
|
+
Args:
|
|
561
|
+
message_id[str]: Id of the message to be marked as read
|
|
562
|
+
|
|
563
|
+
Returns:
|
|
564
|
+
Dict[Any, Any]: Response from the API
|
|
565
|
+
|
|
566
|
+
Example:
|
|
567
|
+
>>> from whatsapp import WhatsApp
|
|
568
|
+
>>> whatsapp = WhatsApp(token, phone_number_id)
|
|
569
|
+
>>> whatsapp.mark_as_read("message_id")
|
|
570
|
+
"""
|
|
571
|
+
headers = {
|
|
572
|
+
"Authorization": f"Bearer {self.token}",
|
|
573
|
+
"Content-Type": "application/json",
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
json_data = {
|
|
577
|
+
"messaging_product": "whatsapp",
|
|
578
|
+
"status": "read",
|
|
579
|
+
"message_id": message_id,
|
|
580
|
+
}
|
|
581
|
+
logging.info(f"Marking message {message_id} as read")
|
|
582
|
+
response = requests.post(
|
|
583
|
+
f"{self.v15_base_url}/{self.phone_number_id}/messages",
|
|
584
|
+
headers=headers,
|
|
585
|
+
json=json_data,
|
|
586
|
+
).json()
|
|
587
|
+
if response.status_code == 200:
|
|
588
|
+
logging.info(f"Message {message_id} marked as read")
|
|
589
|
+
return response
|
|
590
|
+
logging.info(f"Error marking message {message_id} as read")
|
|
591
|
+
logging.info(f"Status code: {response.status_code}")
|
|
592
|
+
logging.info(f"Response: {response.json()}")
|
|
593
|
+
return response
|
|
594
|
+
|
|
595
|
+
def mark_as_read_by_winter(self, message_id: str):
|
|
596
|
+
"""
|
|
597
|
+
Marks a message as read
|
|
598
|
+
|
|
599
|
+
Args:
|
|
600
|
+
message_id[str]: Id of the message to be marked as read
|
|
601
|
+
|
|
602
|
+
Returns:
|
|
603
|
+
Dict[Any, Any]: Response from the API
|
|
604
|
+
|
|
605
|
+
Example:
|
|
606
|
+
>>> from whatsapp import WhatsApp
|
|
607
|
+
>>> whatsapp = WhatsApp(token, phone_number_id)
|
|
608
|
+
>>> whatsapp.mark_as_read("message_id")
|
|
609
|
+
"""
|
|
610
|
+
headers = {
|
|
611
|
+
"Authorization": f"Bearer {self.token}",
|
|
612
|
+
"Content-Type": "application/json",
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
json_data = {
|
|
616
|
+
"messaging_product": "whatsapp",
|
|
617
|
+
"status": "read",
|
|
618
|
+
"message_id": message_id,
|
|
619
|
+
}
|
|
620
|
+
logging.info(f"Marking message {message_id} as read")
|
|
621
|
+
requests.post(
|
|
622
|
+
f"{self.v15_base_url}/{self.phone_number_id}/messages",
|
|
623
|
+
headers=headers,
|
|
624
|
+
json=json_data,
|
|
625
|
+
).json()
|
|
626
|
+
|
|
627
|
+
def create_button(self, button: Dict[Any, Any]) -> Dict[Any, Any]:
|
|
628
|
+
"""
|
|
629
|
+
Method to create a button object to be used in the send_message method.
|
|
630
|
+
|
|
631
|
+
This is method is designed to only be used internally by the send_button method.
|
|
632
|
+
|
|
633
|
+
Args:
|
|
634
|
+
button[dict]: A dictionary containing the button data
|
|
635
|
+
"""
|
|
636
|
+
data = {"type": "list", "action": button.get("action")}
|
|
637
|
+
if button.get("header"):
|
|
638
|
+
data["header"] = {"type": "text", "text": button.get("header")}
|
|
639
|
+
if button.get("body"):
|
|
640
|
+
data["body"] = {"text": button.get("body")}
|
|
641
|
+
if button.get("footer"):
|
|
642
|
+
data["footer"] = {"text": button.get("footer")}
|
|
643
|
+
return data
|
|
644
|
+
|
|
645
|
+
def send_button(self, button: Dict[Any, Any], recipient_id: str) -> Dict[Any, Any]:
|
|
646
|
+
"""
|
|
647
|
+
Sends an interactive buttons message to a WhatsApp user
|
|
648
|
+
|
|
649
|
+
Args:
|
|
650
|
+
button[dict]: A dictionary containing the button data(rows-title may not exceed 20 characters)
|
|
651
|
+
recipient_id[str]: Phone number of the user with country code wihout +
|
|
652
|
+
|
|
653
|
+
check https://github.com/Neurotech-HQ/heyoo#sending-interactive-reply-buttons for an example.
|
|
654
|
+
"""
|
|
655
|
+
data = {
|
|
656
|
+
"messaging_product": "whatsapp",
|
|
657
|
+
"to": recipient_id,
|
|
658
|
+
"type": "interactive",
|
|
659
|
+
"interactive": self.create_button(button),
|
|
660
|
+
}
|
|
661
|
+
logging.info(f"Sending buttons to {recipient_id}")
|
|
662
|
+
r = requests.post(self.url, headers=self.headers, json=data)
|
|
663
|
+
if r.status_code == 200:
|
|
664
|
+
logging.info(f"Buttons sent to {recipient_id}")
|
|
665
|
+
return r.json()
|
|
666
|
+
logging.info(f"Buttons not sent to {recipient_id}")
|
|
667
|
+
logging.info(f"Status code: {r.status_code}")
|
|
668
|
+
logging.info(f"Response: {r.json()}")
|
|
669
|
+
return r.json()
|
|
670
|
+
|
|
671
|
+
def send_reply_button(
|
|
672
|
+
self, button: Dict[Any, Any], recipient_id: str
|
|
673
|
+
) -> Dict[Any, Any]:
|
|
674
|
+
"""
|
|
675
|
+
Sends an interactive reply buttons[menu] message to a WhatsApp user
|
|
676
|
+
|
|
677
|
+
Args:
|
|
678
|
+
button[dict]: A dictionary containing the button data
|
|
679
|
+
recipient_id[str]: Phone number of the user with country code wihout +
|
|
680
|
+
|
|
681
|
+
Note:
|
|
682
|
+
The maximum number of buttons is 3, more than 3 buttons will rise an error.
|
|
683
|
+
"""
|
|
684
|
+
data = {
|
|
685
|
+
"messaging_product": "whatsapp",
|
|
686
|
+
"recipient_type": "individual",
|
|
687
|
+
"to": recipient_id,
|
|
688
|
+
"type": "interactive",
|
|
689
|
+
"interactive": button,
|
|
690
|
+
}
|
|
691
|
+
r = requests.post(self.url, headers=self.headers, json=data)
|
|
692
|
+
if r.status_code == 200:
|
|
693
|
+
logging.info(f"Reply buttons sent to {recipient_id}")
|
|
694
|
+
return r.json()
|
|
695
|
+
logging.info(f"Reply buttons not sent to {recipient_id}")
|
|
696
|
+
logging.info(f"Status code: {r.status_code}")
|
|
697
|
+
logging.info(f"Response: {r.json()}")
|
|
698
|
+
return r.json()
|
|
699
|
+
|
|
700
|
+
def query_media_url(self, media_id: str) -> Union[str, None]:
|
|
701
|
+
"""
|
|
702
|
+
Query media url from media id obtained either by manually uploading media or received media
|
|
703
|
+
|
|
704
|
+
Args:
|
|
705
|
+
media_id[str]: Media id of the media
|
|
706
|
+
|
|
707
|
+
Returns:
|
|
708
|
+
str: Media url
|
|
709
|
+
|
|
710
|
+
Example:
|
|
711
|
+
>>> from whatsapp import WhatsApp
|
|
712
|
+
>>> whatsapp = WhatsApp(token, phone_number_id)
|
|
713
|
+
>>> whatsapp.query_media_url("media_id")
|
|
714
|
+
"""
|
|
715
|
+
|
|
716
|
+
logging.info(f"Querying media url for {media_id}")
|
|
717
|
+
r = requests.get(f"{self.base_url}/{media_id}", headers=self.headers)
|
|
718
|
+
if r.status_code == 200:
|
|
719
|
+
logging.info(f"Media url queried for {media_id}")
|
|
720
|
+
return r.json()["url"]
|
|
721
|
+
logging.info(f"Media url not queried for {media_id}")
|
|
722
|
+
logging.info(f"Status code: {r.status_code}")
|
|
723
|
+
logging.info(f"Response: {r.json()}")
|
|
724
|
+
return None
|
|
725
|
+
|
|
726
|
+
def download_media(
|
|
727
|
+
self, media_url: str, mime_type: str, file_path: str = "temp"
|
|
728
|
+
) -> Union[str, None]:
|
|
729
|
+
"""
|
|
730
|
+
Download media from media url obtained either by manually uploading media or received media
|
|
731
|
+
|
|
732
|
+
Args:
|
|
733
|
+
media_url[str]: Media url of the media
|
|
734
|
+
mime_type[str]: Mime type of the media
|
|
735
|
+
file_path[str]: Path of the file to be downloaded to. Default is "temp"
|
|
736
|
+
Do not include the file extension. It will be added automatically.
|
|
737
|
+
|
|
738
|
+
Returns:
|
|
739
|
+
str: Media url
|
|
740
|
+
|
|
741
|
+
Example:
|
|
742
|
+
>>> from whatsapp import WhatsApp
|
|
743
|
+
>>> whatsapp = WhatsApp(token, phone_number_id)
|
|
744
|
+
>>> whatsapp.download_media("media_url", "image/jpeg")
|
|
745
|
+
>>> whatsapp.download_media("media_url", "video/mp4", "path/to/file") #do not include the file extension
|
|
746
|
+
"""
|
|
747
|
+
r = requests.get(media_url, headers=self.headers)
|
|
748
|
+
content = r.content
|
|
749
|
+
extension = mime_type.split("/")[1]
|
|
750
|
+
# create a temporary file
|
|
751
|
+
try:
|
|
752
|
+
save_file_here = (
|
|
753
|
+
f"{file_path}.{extension}" if file_path else f"temp.{extension}"
|
|
754
|
+
)
|
|
755
|
+
with open(save_file_here, "wb") as f:
|
|
756
|
+
f.write(content)
|
|
757
|
+
logging.info(f"Media downloaded to {save_file_here}")
|
|
758
|
+
return f.name
|
|
759
|
+
except Exception as e:
|
|
760
|
+
logging.info(e)
|
|
761
|
+
logging.ERROR(f"Error downloading media to {save_file_here}")
|
|
762
|
+
return None
|
|
763
|
+
|
|
764
|
+
def preprocess(self, data: Dict[Any, Any]) -> Dict[Any, Any]:
|
|
765
|
+
"""
|
|
766
|
+
Preprocesses the data received from the webhook.
|
|
767
|
+
|
|
768
|
+
This method is designed to only be used internally.
|
|
769
|
+
|
|
770
|
+
Args:
|
|
771
|
+
data[dict]: The data received from the webhook
|
|
772
|
+
"""
|
|
773
|
+
return data["entry"][0]["changes"][0]["value"]
|
|
774
|
+
|
|
775
|
+
def is_message(self, data: Dict[Any, Any]) -> bool:
|
|
776
|
+
"""is_message checks if the data received from the webhook is a message.
|
|
777
|
+
|
|
778
|
+
Args:
|
|
779
|
+
data (Dict[Any, Any]): The data received from the webhook
|
|
780
|
+
|
|
781
|
+
Returns:
|
|
782
|
+
bool: True if the data is a message, False otherwise
|
|
783
|
+
"""
|
|
784
|
+
data = self.preprocess(data)
|
|
785
|
+
if "messages" in data:
|
|
786
|
+
return True
|
|
787
|
+
else:
|
|
788
|
+
return False
|
|
789
|
+
|
|
790
|
+
def get_mobile(self, data: Dict[Any, Any]) -> Union[str, None]:
|
|
791
|
+
"""
|
|
792
|
+
Extracts the mobile number of the sender from the data received from the webhook.
|
|
793
|
+
|
|
794
|
+
Args:
|
|
795
|
+
data[dict]: The data received from the webhook
|
|
796
|
+
Returns:
|
|
797
|
+
str: The mobile number of the sender
|
|
798
|
+
|
|
799
|
+
Example:
|
|
800
|
+
>>> from whatsapp import WhatsApp
|
|
801
|
+
>>> whatsapp = WhatsApp(token, phone_number_id)
|
|
802
|
+
>>> mobile = whatsapp.get_mobile(data)
|
|
803
|
+
"""
|
|
804
|
+
data = self.preprocess(data)
|
|
805
|
+
if "contacts" in data:
|
|
806
|
+
return data["contacts"][0]["wa_id"]
|
|
807
|
+
|
|
808
|
+
def get_name(self, data: Dict[Any, Any]) -> Union[str, None]:
|
|
809
|
+
"""
|
|
810
|
+
Extracts the name of the sender from the data received from the webhook.
|
|
811
|
+
|
|
812
|
+
Args:
|
|
813
|
+
data[dict]: The data received from the webhook
|
|
814
|
+
Returns:
|
|
815
|
+
str: The name of the sender
|
|
816
|
+
Example:
|
|
817
|
+
>>> from whatsapp import WhatsApp
|
|
818
|
+
>>> whatsapp = WhatsApp(token, phone_number_id)
|
|
819
|
+
>>> mobile = whatsapp.get_name(data)
|
|
820
|
+
"""
|
|
821
|
+
contact = self.preprocess(data)
|
|
822
|
+
if contact:
|
|
823
|
+
return contact["contacts"][0]["profile"]["name"]
|
|
824
|
+
|
|
825
|
+
def get_message(self, data: Dict[Any, Any]) -> Union[str, None]:
|
|
826
|
+
"""
|
|
827
|
+
Extracts the text message of the sender from the data received from the webhook.
|
|
828
|
+
|
|
829
|
+
Args:
|
|
830
|
+
data[dict]: The data received from the webhook
|
|
831
|
+
Returns:
|
|
832
|
+
str: The text message received from the sender
|
|
833
|
+
Example:
|
|
834
|
+
>>> from whatsapp import WhatsApp
|
|
835
|
+
>>> whatsapp = WhatsApp(token, phone_number_id)
|
|
836
|
+
>>> message = message.get_message(data)
|
|
837
|
+
"""
|
|
838
|
+
data = self.preprocess(data)
|
|
839
|
+
if "messages" in data:
|
|
840
|
+
return data["messages"][0]["text"]["body"]
|
|
841
|
+
|
|
842
|
+
def get_message_id(self, data: Dict[Any, Any]) -> Union[str, None]:
|
|
843
|
+
"""
|
|
844
|
+
Extracts the message id of the sender from the data received from the webhook.
|
|
845
|
+
|
|
846
|
+
Args:
|
|
847
|
+
data[dict]: The data received from the webhook
|
|
848
|
+
Returns:
|
|
849
|
+
str: The message id of the sender
|
|
850
|
+
Example:
|
|
851
|
+
>>> from whatsapp import WhatsApp
|
|
852
|
+
>>> whatsapp = WhatsApp(token, phone_number_id)
|
|
853
|
+
>>> message_id = whatsapp.get_message_id(data)
|
|
854
|
+
"""
|
|
855
|
+
data = self.preprocess(data)
|
|
856
|
+
if "messages" in data:
|
|
857
|
+
return data["messages"][0]["id"]
|
|
858
|
+
return None
|
|
859
|
+
|
|
860
|
+
def get_conversation_id(self, data: Dict[Any, Any]) -> Union[str, None]:
|
|
861
|
+
"""
|
|
862
|
+
Extracts the conversation id from the data received from the webhook.
|
|
863
|
+
|
|
864
|
+
Args:
|
|
865
|
+
data[dict]: The data received from the webhook
|
|
866
|
+
Returns:
|
|
867
|
+
str: The conversation id, or None if not found
|
|
868
|
+
Example:
|
|
869
|
+
>>> from whatsapp import WhatsApp
|
|
870
|
+
>>> whatsapp = WhatsApp(token, phone_number_id)
|
|
871
|
+
>>> conversation_id = whatsapp.get_conversation_id(data)
|
|
872
|
+
"""
|
|
873
|
+
data = self.preprocess(data)
|
|
874
|
+
if "conversation_id" in data:
|
|
875
|
+
return data.get("conversation_id")
|
|
876
|
+
return None
|
|
877
|
+
|
|
878
|
+
def get_message_timestamp(self, data: Dict[Any, Any]) -> Union[str, None]:
|
|
879
|
+
""" "
|
|
880
|
+
Extracts the timestamp of the message from the data received from the webhook.
|
|
881
|
+
|
|
882
|
+
Args:
|
|
883
|
+
data[dict]: The data received from the webhook
|
|
884
|
+
Returns:
|
|
885
|
+
str: The timestamp of the message
|
|
886
|
+
Example:
|
|
887
|
+
>>> from whatsapp import WhatsApp
|
|
888
|
+
>>> whatsapp = WhatsApp(token, phone_number_id)
|
|
889
|
+
>>> whatsapp.get_message_timestamp(data)
|
|
890
|
+
"""
|
|
891
|
+
data = self.preprocess(data)
|
|
892
|
+
if "messages" in data:
|
|
893
|
+
return data["messages"][0]["timestamp"]
|
|
894
|
+
|
|
895
|
+
def get_interactive_response(self, data: Dict[Any, Any]) -> Union[Dict, None]:
|
|
896
|
+
"""
|
|
897
|
+
Extracts the response of the interactive message from the data received from the webhook.
|
|
898
|
+
|
|
899
|
+
Args:
|
|
900
|
+
data[dict]: The data received from the webhook
|
|
901
|
+
Returns:
|
|
902
|
+
dict: The response of the interactive message
|
|
903
|
+
|
|
904
|
+
Example:
|
|
905
|
+
>>> from whatsapp import WhatsApp
|
|
906
|
+
>>> whatsapp = WhatsApp(token, phone_number_id)
|
|
907
|
+
>>> response = whatsapp.get_interactive_response(data)
|
|
908
|
+
>>> interactive_type = response.get("type")
|
|
909
|
+
>>> message_id = response[interactive_type]["id"]
|
|
910
|
+
>>> message_text = response[interactive_type]["title"]
|
|
911
|
+
"""
|
|
912
|
+
data = self.preprocess(data)
|
|
913
|
+
if "messages" in data:
|
|
914
|
+
if "interactive" in data["messages"][0]:
|
|
915
|
+
return data["messages"][0]["interactive"]
|
|
916
|
+
|
|
917
|
+
def get_location(self, data: Dict[Any, Any]) -> Union[Dict, None]:
|
|
918
|
+
"""
|
|
919
|
+
Extracts the location of the sender from the data received from the webhook.
|
|
920
|
+
|
|
921
|
+
Args:
|
|
922
|
+
data[dict]: The data received from the webhook
|
|
923
|
+
|
|
924
|
+
Returns:
|
|
925
|
+
dict: The location of the sender
|
|
926
|
+
|
|
927
|
+
Example:
|
|
928
|
+
>>> from whatsapp import WhatsApp
|
|
929
|
+
>>> whatsapp = WhatsApp(token, phone_number_id)
|
|
930
|
+
>>> whatsapp.get_location(data)
|
|
931
|
+
"""
|
|
932
|
+
data = self.preprocess(data)
|
|
933
|
+
if "messages" in data:
|
|
934
|
+
if "location" in data["messages"][0]:
|
|
935
|
+
return data["messages"][0]["location"]
|
|
936
|
+
|
|
937
|
+
def get_image(self, data: Dict[Any, Any]) -> Union[Dict, None]:
|
|
938
|
+
""" "
|
|
939
|
+
Extracts the image of the sender from the data received from the webhook.
|
|
940
|
+
|
|
941
|
+
Args:
|
|
942
|
+
data[dict]: The data received from the webhook
|
|
943
|
+
Returns:
|
|
944
|
+
dict: The image_id of an image sent by the sender
|
|
945
|
+
|
|
946
|
+
Example:
|
|
947
|
+
>>> from whatsapp import WhatsApp
|
|
948
|
+
>>> whatsapp = WhatsApp(token, phone_number_id)
|
|
949
|
+
>>> image_id = whatsapp.get_image(data)
|
|
950
|
+
"""
|
|
951
|
+
data = self.preprocess(data)
|
|
952
|
+
if "messages" in data:
|
|
953
|
+
if "image" in data["messages"][0]:
|
|
954
|
+
return data["messages"][0]["image"]
|
|
955
|
+
|
|
956
|
+
def get_document(self, data: Dict[Any, Any]) -> Union[Dict, None]:
|
|
957
|
+
""" "
|
|
958
|
+
Extracts the document of the sender from the data received from the webhook.
|
|
959
|
+
|
|
960
|
+
Args:
|
|
961
|
+
data[dict]: The data received from the webhook
|
|
962
|
+
Returns:
|
|
963
|
+
dict: The document_id of an image sent by the sender
|
|
964
|
+
|
|
965
|
+
Example:
|
|
966
|
+
>>> from whatsapp import WhatsApp
|
|
967
|
+
>>> whatsapp = WhatsApp(token, phone_number_id)
|
|
968
|
+
>>> document_id = whatsapp.get_document(data)
|
|
969
|
+
"""
|
|
970
|
+
data = self.preprocess(data)
|
|
971
|
+
if "messages" in data:
|
|
972
|
+
if "document" in data["messages"][0]:
|
|
973
|
+
return data["messages"][0]["document"]
|
|
974
|
+
|
|
975
|
+
def get_audio(self, data: Dict[Any, Any]) -> Union[Dict, None]:
|
|
976
|
+
"""
|
|
977
|
+
Extracts the audio of the sender from the data received from the webhook.
|
|
978
|
+
|
|
979
|
+
Args:
|
|
980
|
+
data[dict]: The data received from the webhook
|
|
981
|
+
|
|
982
|
+
Returns:
|
|
983
|
+
dict: The audio of the sender
|
|
984
|
+
|
|
985
|
+
Example:
|
|
986
|
+
>>> from whatsapp import WhatsApp
|
|
987
|
+
>>> whatsapp = WhatsApp(token, phone_number_id)
|
|
988
|
+
>>> whatsapp.get_audio(data)
|
|
989
|
+
"""
|
|
990
|
+
data = self.preprocess(data)
|
|
991
|
+
if "messages" in data:
|
|
992
|
+
if "audio" in data["messages"][0]:
|
|
993
|
+
return data["messages"][0]["audio"]
|
|
994
|
+
|
|
995
|
+
def get_video(self, data: Dict[Any, Any]) -> Union[Dict, None]:
|
|
996
|
+
"""
|
|
997
|
+
Extracts the video of the sender from the data received from the webhook.
|
|
998
|
+
|
|
999
|
+
Args:
|
|
1000
|
+
data[dict]: The data received from the webhook
|
|
1001
|
+
|
|
1002
|
+
Returns:
|
|
1003
|
+
dict: Dictionary containing the video details sent by the sender
|
|
1004
|
+
|
|
1005
|
+
Example:
|
|
1006
|
+
>>> from whatsapp import WhatsApp
|
|
1007
|
+
>>> whatsapp = WhatsApp(token, phone_number_id)
|
|
1008
|
+
>>> whatsapp.get_video(data)
|
|
1009
|
+
"""
|
|
1010
|
+
data = self.preprocess(data)
|
|
1011
|
+
if "messages" in data:
|
|
1012
|
+
if "video" in data["messages"][0]:
|
|
1013
|
+
return data["messages"][0]["video"]
|
|
1014
|
+
|
|
1015
|
+
def get_message_type(self, data: Dict[Any, Any]) -> Union[str, None]:
|
|
1016
|
+
"""
|
|
1017
|
+
Gets the type of the message sent by the sender from the data received from the webhook.
|
|
1018
|
+
|
|
1019
|
+
|
|
1020
|
+
Args:
|
|
1021
|
+
data [dict]: The data received from the webhook
|
|
1022
|
+
|
|
1023
|
+
Returns:
|
|
1024
|
+
str: The type of the message sent by the sender
|
|
1025
|
+
|
|
1026
|
+
Example:
|
|
1027
|
+
>>> from whatsapp import WhatsApp
|
|
1028
|
+
>>> whatsapp = WhatsApp(token, phone_number_id)
|
|
1029
|
+
>>> whatsapp.get_message_type(data)
|
|
1030
|
+
"""
|
|
1031
|
+
data = self.preprocess(data)
|
|
1032
|
+
if "messages" in data:
|
|
1033
|
+
return data["messages"][0]["type"]
|
|
1034
|
+
|
|
1035
|
+
def get_delivery(self, data: Dict[Any, Any]) -> Union[Dict, None]:
|
|
1036
|
+
"""
|
|
1037
|
+
Extracts the delivery status of the message from the data received from the webhook.
|
|
1038
|
+
Args:
|
|
1039
|
+
data [dict]: The data received from the webhook
|
|
1040
|
+
|
|
1041
|
+
Returns:
|
|
1042
|
+
dict: The delivery status of the message and message id of the message
|
|
1043
|
+
"""
|
|
1044
|
+
data = self.preprocess(data)
|
|
1045
|
+
if "statuses" in data:
|
|
1046
|
+
return data["statuses"][0]["status"]
|
|
1047
|
+
|
|
1048
|
+
def changed_field(self, data: Dict[Any, Any]) -> str:
|
|
1049
|
+
"""
|
|
1050
|
+
Helper function to check if the field changed in the data received from the webhook.
|
|
1051
|
+
|
|
1052
|
+
Args:
|
|
1053
|
+
data [dict]: The data received from the webhook
|
|
1054
|
+
|
|
1055
|
+
Returns:
|
|
1056
|
+
str: The field changed in the data received from the webhook
|
|
1057
|
+
|
|
1058
|
+
Example:
|
|
1059
|
+
>>> from whatsapp import WhatsApp
|
|
1060
|
+
>>> whatsapp = WhatsApp(token, phone_number_id)
|
|
1061
|
+
>>> whatsapp.changed_field(data)
|
|
1062
|
+
"""
|
|
1063
|
+
return data["entry"][0]["changes"][0]["field"]
|