whatsapp-python 4.2.0__py3-none-any.whl → 4.3.0__py3-none-any.whl
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.
- whatsapp/__init__.py +213 -82
- whatsapp/async_ext/_buttons.py +9 -5
- whatsapp/async_ext/_media.py +24 -24
- whatsapp/async_ext/_message.py +24 -10
- whatsapp/async_ext/_send_media.py +53 -38
- whatsapp/async_ext/_send_others.py +10 -6
- whatsapp/async_ext/_static.py +2 -0
- whatsapp/constants.py +1 -1
- whatsapp/errors.py +290 -0
- whatsapp/ext/_buttons.py +6 -3
- whatsapp/ext/_media.py +11 -6
- whatsapp/ext/_message.py +17 -7
- whatsapp/ext/_send_media.py +41 -30
- whatsapp/ext/_send_others.py +3 -2
- whatsapp/ext/_static.py +2 -0
- {whatsapp_python-4.2.0.dist-info → whatsapp_python-4.3.0.dist-info}/METADATA +16 -17
- whatsapp_python-4.3.0.dist-info/RECORD +21 -0
- whatsapp_python-4.2.0.dist-info/RECORD +0 -20
- {whatsapp_python-4.2.0.dist-info → whatsapp_python-4.3.0.dist-info}/WHEEL +0 -0
- {whatsapp_python-4.2.0.dist-info → whatsapp_python-4.3.0.dist-info}/licenses/LICENSE +0 -0
whatsapp/__init__.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Unofficial Python wrapper for the WhatsApp Cloud API.
|
|
3
3
|
"""
|
|
4
|
+
|
|
4
5
|
from __future__ import annotations
|
|
5
6
|
import requests
|
|
6
7
|
import logging
|
|
@@ -14,22 +15,95 @@ from .constants import VERSION
|
|
|
14
15
|
from .ext._property import authorized
|
|
15
16
|
from .ext._send_others import send_custom_json, send_contacts
|
|
16
17
|
from .ext._message import send_template
|
|
17
|
-
from .ext._send_media import
|
|
18
|
+
from .ext._send_media import (
|
|
19
|
+
send_image,
|
|
20
|
+
send_video,
|
|
21
|
+
send_audio,
|
|
22
|
+
send_location,
|
|
23
|
+
send_sticker,
|
|
24
|
+
send_document,
|
|
25
|
+
)
|
|
18
26
|
from .ext._media import upload_media, query_media_url, download_media, delete_media
|
|
19
27
|
from .ext._buttons import send_button, create_button, send_reply_button
|
|
20
|
-
from .ext._static import
|
|
28
|
+
from .ext._static import (
|
|
29
|
+
is_message,
|
|
30
|
+
get_mobile,
|
|
31
|
+
get_author,
|
|
32
|
+
get_name,
|
|
33
|
+
get_message,
|
|
34
|
+
get_message_id,
|
|
35
|
+
get_message_type,
|
|
36
|
+
get_message_timestamp,
|
|
37
|
+
get_audio,
|
|
38
|
+
get_delivery,
|
|
39
|
+
get_document,
|
|
40
|
+
get_image,
|
|
41
|
+
get_sticker,
|
|
42
|
+
get_interactive_response,
|
|
43
|
+
get_location,
|
|
44
|
+
get_video,
|
|
45
|
+
changed_field,
|
|
46
|
+
)
|
|
21
47
|
|
|
22
48
|
from .async_ext._property import authorized as async_authorized
|
|
23
|
-
from .async_ext._send_others import
|
|
49
|
+
from .async_ext._send_others import (
|
|
50
|
+
send_custom_json as async_send_custom_json,
|
|
51
|
+
send_contacts as async_send_contacts,
|
|
52
|
+
)
|
|
24
53
|
from .async_ext._message import send_template as async_send_template
|
|
25
|
-
from .async_ext._send_media import
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
54
|
+
from .async_ext._send_media import (
|
|
55
|
+
send_image as async_send_image,
|
|
56
|
+
send_video as async_send_video,
|
|
57
|
+
send_audio as async_send_audio,
|
|
58
|
+
send_location as async_send_location,
|
|
59
|
+
send_sticker as async_send_sticker,
|
|
60
|
+
send_document as async_send_document,
|
|
61
|
+
)
|
|
62
|
+
from .async_ext._media import (
|
|
63
|
+
upload_media as async_upload_media,
|
|
64
|
+
query_media_url as async_query_media_url,
|
|
65
|
+
download_media as async_download_media,
|
|
66
|
+
delete_media as async_delete_media,
|
|
67
|
+
)
|
|
68
|
+
from .async_ext._buttons import (
|
|
69
|
+
send_button as async_send_button,
|
|
70
|
+
create_button as async_create_button,
|
|
71
|
+
send_reply_button as async_send_reply_button,
|
|
72
|
+
)
|
|
73
|
+
from .async_ext._static import (
|
|
74
|
+
is_message as async_is_message,
|
|
75
|
+
get_mobile as async_get_mobile,
|
|
76
|
+
get_author as async_get_author,
|
|
77
|
+
get_name as async_get_name,
|
|
78
|
+
get_message as async_get_message,
|
|
79
|
+
get_message_id as async_get_message_id,
|
|
80
|
+
get_message_type as async_get_message_type,
|
|
81
|
+
get_message_timestamp as async_get_message_timestamp,
|
|
82
|
+
get_audio as async_get_audio,
|
|
83
|
+
get_delivery as async_get_delivery,
|
|
84
|
+
get_document as async_get_document,
|
|
85
|
+
get_image as async_get_image,
|
|
86
|
+
get_sticker as async_get_sticker,
|
|
87
|
+
get_interactive_response as async_get_interactive_response,
|
|
88
|
+
get_location as async_get_location,
|
|
89
|
+
get_video as async_get_video,
|
|
90
|
+
changed_field as async_changed_field,
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
from .errors import Handle
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class WhatsApp:
|
|
97
|
+
def __init__(
|
|
98
|
+
self,
|
|
99
|
+
token: str = "",
|
|
100
|
+
phone_number_id: dict = "",
|
|
101
|
+
logger: bool = True,
|
|
102
|
+
update_check: bool = True,
|
|
103
|
+
verify_token: str = "",
|
|
104
|
+
debug: bool = True,
|
|
105
|
+
version: str = "latest",
|
|
106
|
+
):
|
|
33
107
|
"""
|
|
34
108
|
Initialize the WhatsApp Object
|
|
35
109
|
|
|
@@ -50,42 +124,49 @@ class WhatsApp(object):
|
|
|
50
124
|
|
|
51
125
|
elif phone_number_id == "":
|
|
52
126
|
logging.error("Phone number ID not provided")
|
|
53
|
-
raise ValueError(
|
|
54
|
-
"Phone number ID not provided but required")
|
|
127
|
+
raise ValueError("Phone number ID not provided but required")
|
|
55
128
|
elif isinstance(phone_number_id, str):
|
|
56
129
|
logging.critical(
|
|
57
|
-
"The phone number ID should be a dictionary of phone numbers and their IDs. Using strings is deprecated."
|
|
130
|
+
"The phone number ID should be a dictionary of phone numbers and their IDs. Using strings is deprecated."
|
|
131
|
+
)
|
|
58
132
|
raise ValueError(
|
|
59
|
-
"Phone number ID should be a dictionary of phone numbers and their IDs"
|
|
133
|
+
"Phone number ID should be a dictionary of phone numbers and their IDs"
|
|
134
|
+
)
|
|
60
135
|
else:
|
|
61
136
|
pass
|
|
62
137
|
|
|
63
138
|
self.VERSION = VERSION # package version
|
|
64
|
-
r = requests.get(
|
|
139
|
+
r = requests.get(
|
|
140
|
+
"https://developers.facebook.com/docs/graph-api/changelog/"
|
|
141
|
+
).text
|
|
65
142
|
|
|
66
143
|
# dynamically get the latest version of the API
|
|
67
144
|
if version == "latest":
|
|
68
145
|
soup = BeautifulSoup(r, features="html.parser")
|
|
69
146
|
t1 = soup.findAll("table")
|
|
70
147
|
|
|
71
|
-
def makeversion(table):
|
|
148
|
+
def makeversion(table: BeautifulSoup) -> str:
|
|
72
149
|
result = []
|
|
73
|
-
allrows = table.findAll(
|
|
150
|
+
allrows = table.findAll("tr")
|
|
74
151
|
for row in allrows:
|
|
75
152
|
result.append([])
|
|
76
|
-
allcols = row.findAll(
|
|
153
|
+
allcols = row.findAll("td")
|
|
77
154
|
for col in allcols:
|
|
78
155
|
thestrings = [(s) for s in col.findAll(text=True)]
|
|
79
|
-
thetext =
|
|
156
|
+
thetext = "".join(thestrings)
|
|
80
157
|
result[-1].append(thetext)
|
|
81
158
|
return result[0][1]
|
|
159
|
+
|
|
82
160
|
self.LATEST = makeversion(t1[0]) # latest version of the API
|
|
83
161
|
else:
|
|
84
162
|
self.LATEST = version
|
|
85
163
|
|
|
86
164
|
if update_check is True:
|
|
87
|
-
latest = str(
|
|
88
|
-
"https://pypi.org/pypi/whatsapp-python/json").json()[
|
|
165
|
+
latest = str(
|
|
166
|
+
requests.get("https://pypi.org/pypi/whatsapp-python/json").json()[
|
|
167
|
+
"info"
|
|
168
|
+
]["version"]
|
|
169
|
+
)
|
|
89
170
|
if self.VERSION != latest:
|
|
90
171
|
try:
|
|
91
172
|
version_int = int(self.VERSION.replace(".", ""))
|
|
@@ -99,18 +180,19 @@ class WhatsApp(object):
|
|
|
99
180
|
if version_int < latest_int:
|
|
100
181
|
if version_int == 0:
|
|
101
182
|
logging.critical(
|
|
102
|
-
f"There was an error while checking for updates, please check for updates manually. This may be due to the version being a post-release version (e.g. 1.0.0.post1) or a pre-release version (e.g. 1.0.0a1). READ THE CHANGELOG BEFORE UPDATING. NEW VERSIONS MAY BREAK YOUR CODE IF NOT PROPERLY UPDATED."
|
|
183
|
+
f"There was an error while checking for updates, please check for updates manually. This may be due to the version being a post-release version (e.g. 1.0.0.post1) or a pre-release version (e.g. 1.0.0a1). READ THE CHANGELOG BEFORE UPDATING. NEW VERSIONS MAY BREAK YOUR CODE IF NOT PROPERLY UPDATED."
|
|
184
|
+
)
|
|
103
185
|
else:
|
|
104
186
|
logging.critical(
|
|
105
|
-
f"Whatsapp-python is out of date. Please update to the latest version {latest}. READ THE CHANGELOG BEFORE UPDATING. NEW VERSIONS MAY BREAK YOUR CODE IF NOT PROPERLY UPDATED."
|
|
187
|
+
f"Whatsapp-python is out of date. Please update to the latest version {latest}. READ THE CHANGELOG BEFORE UPDATING. NEW VERSIONS MAY BREAK YOUR CODE IF NOT PROPERLY UPDATED."
|
|
188
|
+
)
|
|
106
189
|
|
|
107
190
|
if token == "":
|
|
108
191
|
logging.error("Token not provided")
|
|
109
192
|
raise ValueError("Token not provided but required")
|
|
110
193
|
if phone_number_id == "":
|
|
111
194
|
logging.error("Phone number ID not provided")
|
|
112
|
-
raise ValueError(
|
|
113
|
-
"Phone number ID not provided but required")
|
|
195
|
+
raise ValueError("Phone number ID not provided but required")
|
|
114
196
|
self.token = token
|
|
115
197
|
self.phone_number_id = phone_number_id
|
|
116
198
|
self.base_url = f"https://graph.facebook.com/{self.LATEST}"
|
|
@@ -119,12 +201,13 @@ class WhatsApp(object):
|
|
|
119
201
|
|
|
120
202
|
async def base(*args):
|
|
121
203
|
pass
|
|
204
|
+
|
|
122
205
|
self.message_handler = base
|
|
123
206
|
self.other_handler = base
|
|
124
207
|
self.verification_handler = base
|
|
125
208
|
self.headers = {
|
|
126
209
|
"Content-Type": "application/json",
|
|
127
|
-
"Authorization": f"Bearer {self.token}"
|
|
210
|
+
"Authorization": f"Bearer {self.token}",
|
|
128
211
|
}
|
|
129
212
|
if logger is False:
|
|
130
213
|
logging.disable(logging.INFO)
|
|
@@ -171,10 +254,9 @@ class WhatsApp(object):
|
|
|
171
254
|
return {"success": True}
|
|
172
255
|
except Exception as e:
|
|
173
256
|
logging.error(f"Error parsing message: {e}")
|
|
174
|
-
raise HTTPException(
|
|
175
|
-
"success": False,
|
|
176
|
-
|
|
177
|
-
})
|
|
257
|
+
raise HTTPException(
|
|
258
|
+
status_code=500, detail={"success": False, "error": str(e)}
|
|
259
|
+
)
|
|
178
260
|
|
|
179
261
|
# all the files starting with _ are imported here, and should not be imported directly.
|
|
180
262
|
|
|
@@ -214,7 +296,6 @@ class WhatsApp(object):
|
|
|
214
296
|
send_contacts = send_contacts
|
|
215
297
|
authorized = property(authorized)
|
|
216
298
|
|
|
217
|
-
|
|
218
299
|
def create_message(self, **kwargs) -> Message:
|
|
219
300
|
"""
|
|
220
301
|
Create a message object
|
|
@@ -259,7 +340,16 @@ class WhatsApp(object):
|
|
|
259
340
|
|
|
260
341
|
|
|
261
342
|
class AsyncWhatsApp(WhatsApp):
|
|
262
|
-
def __init__(
|
|
343
|
+
def __init__(
|
|
344
|
+
self,
|
|
345
|
+
token: str = "",
|
|
346
|
+
phone_number_id: dict = "",
|
|
347
|
+
logger: bool = True,
|
|
348
|
+
update_check: bool = True,
|
|
349
|
+
verify_token: str = "",
|
|
350
|
+
debug: bool = True,
|
|
351
|
+
version: str = "latest",
|
|
352
|
+
):
|
|
263
353
|
"""
|
|
264
354
|
Initialize the WhatsApp Object
|
|
265
355
|
|
|
@@ -271,7 +361,6 @@ class AsyncWhatsApp(WhatsApp):
|
|
|
271
361
|
|
|
272
362
|
# Check if the version is up to date
|
|
273
363
|
logging.getLogger(__name__).addHandler(logging.NullHandler())
|
|
274
|
-
|
|
275
364
|
self.l = phone_number_id
|
|
276
365
|
|
|
277
366
|
if isinstance(phone_number_id, dict):
|
|
@@ -280,42 +369,49 @@ class AsyncWhatsApp(WhatsApp):
|
|
|
280
369
|
|
|
281
370
|
elif phone_number_id == "":
|
|
282
371
|
logging.error("Phone number ID not provided")
|
|
283
|
-
raise ValueError(
|
|
284
|
-
"Phone number ID not provided but required")
|
|
372
|
+
raise ValueError("Phone number ID not provided but required")
|
|
285
373
|
elif isinstance(phone_number_id, str):
|
|
286
374
|
logging.critical(
|
|
287
|
-
"The phone number ID should be a dictionary of phone numbers and their IDs. Using strings is deprecated."
|
|
375
|
+
"The phone number ID should be a dictionary of phone numbers and their IDs. Using strings is deprecated."
|
|
376
|
+
)
|
|
288
377
|
raise ValueError(
|
|
289
|
-
"Phone number ID should be a dictionary of phone numbers and their IDs"
|
|
378
|
+
"Phone number ID should be a dictionary of phone numbers and their IDs"
|
|
379
|
+
)
|
|
290
380
|
else:
|
|
291
381
|
pass
|
|
292
382
|
|
|
293
383
|
self.VERSION = VERSION # package version
|
|
294
|
-
r = requests.get(
|
|
384
|
+
r = requests.get(
|
|
385
|
+
"https://developers.facebook.com/docs/graph-api/changelog/"
|
|
386
|
+
).text
|
|
295
387
|
|
|
296
388
|
# dynamically get the latest version of the API
|
|
297
389
|
if version == "latest":
|
|
298
390
|
soup = BeautifulSoup(r, features="html.parser")
|
|
299
391
|
t1 = soup.findAll("table")
|
|
300
392
|
|
|
301
|
-
def makeversion(table):
|
|
393
|
+
def makeversion(table: BeautifulSoup) -> str:
|
|
302
394
|
result = []
|
|
303
|
-
allrows = table.findAll(
|
|
395
|
+
allrows = table.findAll("tr")
|
|
304
396
|
for row in allrows:
|
|
305
397
|
result.append([])
|
|
306
|
-
allcols = row.findAll(
|
|
398
|
+
allcols = row.findAll("td")
|
|
307
399
|
for col in allcols:
|
|
308
400
|
thestrings = [(s) for s in col.findAll(text=True)]
|
|
309
|
-
thetext =
|
|
401
|
+
thetext = "".join(thestrings)
|
|
310
402
|
result[-1].append(thetext)
|
|
311
403
|
return result[0][1]
|
|
404
|
+
|
|
312
405
|
self.LATEST = makeversion(t1[0]) # latest version of the API
|
|
313
406
|
else:
|
|
314
407
|
self.LATEST = version
|
|
315
408
|
|
|
316
409
|
if update_check is True:
|
|
317
|
-
latest = str(
|
|
318
|
-
"https://pypi.org/pypi/whatsapp-python/json").json()[
|
|
410
|
+
latest = str(
|
|
411
|
+
requests.get("https://pypi.org/pypi/whatsapp-python/json").json()[
|
|
412
|
+
"info"
|
|
413
|
+
]["version"]
|
|
414
|
+
)
|
|
319
415
|
if self.VERSION != latest:
|
|
320
416
|
try:
|
|
321
417
|
version_int = int(self.VERSION.replace(".", ""))
|
|
@@ -329,18 +425,19 @@ class AsyncWhatsApp(WhatsApp):
|
|
|
329
425
|
if version_int < latest_int:
|
|
330
426
|
if version_int == 0:
|
|
331
427
|
logging.critical(
|
|
332
|
-
f"There was an error while checking for updates, please check for updates manually. This may be due to the version being a post-release version (e.g. 1.0.0.post1) or a pre-release version (e.g. 1.0.0a1). READ THE CHANGELOG BEFORE UPDATING. NEW VERSIONS MAY BREAK YOUR CODE IF NOT PROPERLY UPDATED."
|
|
428
|
+
f"There was an error while checking for updates, please check for updates manually. This may be due to the version being a post-release version (e.g. 1.0.0.post1) or a pre-release version (e.g. 1.0.0a1). READ THE CHANGELOG BEFORE UPDATING. NEW VERSIONS MAY BREAK YOUR CODE IF NOT PROPERLY UPDATED."
|
|
429
|
+
)
|
|
333
430
|
else:
|
|
334
431
|
logging.critical(
|
|
335
|
-
f"Whatsapp-python is out of date. Please update to the latest version {latest}. READ THE CHANGELOG BEFORE UPDATING. NEW VERSIONS MAY BREAK YOUR CODE IF NOT PROPERLY UPDATED."
|
|
432
|
+
f"Whatsapp-python is out of date. Please update to the latest version {latest}. READ THE CHANGELOG BEFORE UPDATING. NEW VERSIONS MAY BREAK YOUR CODE IF NOT PROPERLY UPDATED."
|
|
433
|
+
)
|
|
336
434
|
|
|
337
435
|
if token == "":
|
|
338
436
|
logging.error("Token not provided")
|
|
339
437
|
raise ValueError("Token not provided but required")
|
|
340
438
|
if phone_number_id == "":
|
|
341
439
|
logging.error("Phone number ID not provided")
|
|
342
|
-
raise ValueError(
|
|
343
|
-
"Phone number ID not provided but required")
|
|
440
|
+
raise ValueError("Phone number ID not provided but required")
|
|
344
441
|
self.token = token
|
|
345
442
|
self.phone_number_id = phone_number_id
|
|
346
443
|
self.base_url = f"https://graph.facebook.com/{self.LATEST}"
|
|
@@ -349,12 +446,13 @@ class AsyncWhatsApp(WhatsApp):
|
|
|
349
446
|
|
|
350
447
|
async def base(*args):
|
|
351
448
|
pass
|
|
449
|
+
|
|
352
450
|
self.message_handler = base
|
|
353
451
|
self.other_handler = base
|
|
354
452
|
self.verification_handler = base
|
|
355
453
|
self.headers = {
|
|
356
454
|
"Content-Type": "application/json",
|
|
357
|
-
"Authorization": f"Bearer {self.token}"
|
|
455
|
+
"Authorization": f"Bearer {self.token}",
|
|
358
456
|
}
|
|
359
457
|
if logger is False:
|
|
360
458
|
logging.disable(logging.INFO)
|
|
@@ -401,10 +499,9 @@ class AsyncWhatsApp(WhatsApp):
|
|
|
401
499
|
return {"success": True}
|
|
402
500
|
except Exception as e:
|
|
403
501
|
logging.error(f"Error parsing message: {e}")
|
|
404
|
-
raise HTTPException(
|
|
405
|
-
"success": False,
|
|
406
|
-
|
|
407
|
-
})
|
|
502
|
+
raise HTTPException(
|
|
503
|
+
status_code=500, detail={"success": False, "error": str(e)}
|
|
504
|
+
)
|
|
408
505
|
|
|
409
506
|
# all the files starting with _ are imported here, and should not be imported directly.
|
|
410
507
|
|
|
@@ -444,8 +541,9 @@ class AsyncWhatsApp(WhatsApp):
|
|
|
444
541
|
send_contacts = async_send_contacts
|
|
445
542
|
authorized = property(async_authorized)
|
|
446
543
|
|
|
544
|
+
def handle(self, data: dict):
|
|
545
|
+
return Handle(data)
|
|
447
546
|
|
|
448
|
-
|
|
449
547
|
def create_message(self, **kwargs) -> AsyncMessage:
|
|
450
548
|
"""
|
|
451
549
|
Create a message object
|
|
@@ -489,10 +587,17 @@ class AsyncWhatsApp(WhatsApp):
|
|
|
489
587
|
_run(self.app, host=host, port=port, **options)
|
|
490
588
|
|
|
491
589
|
|
|
492
|
-
|
|
493
|
-
class Message(object):
|
|
590
|
+
class Message:
|
|
494
591
|
# type: ignore
|
|
495
|
-
def __init__(
|
|
592
|
+
def __init__(
|
|
593
|
+
self,
|
|
594
|
+
id: int = None,
|
|
595
|
+
data: dict = {},
|
|
596
|
+
instance: WhatsApp = None,
|
|
597
|
+
content: str = "",
|
|
598
|
+
to: str = "",
|
|
599
|
+
rec_type: str = "individual",
|
|
600
|
+
):
|
|
496
601
|
self.instance = instance
|
|
497
602
|
self.url = self.instance.url
|
|
498
603
|
self.headers = self.instance.headers
|
|
@@ -509,8 +614,7 @@ class Message(object):
|
|
|
509
614
|
self.rec = rec_type
|
|
510
615
|
self.to = to
|
|
511
616
|
try:
|
|
512
|
-
self.content = content if content != "" else self.instance.get_message(
|
|
513
|
-
data)
|
|
617
|
+
self.content = content if content != "" else self.instance.get_message(data)
|
|
514
618
|
except:
|
|
515
619
|
self.content = content
|
|
516
620
|
try:
|
|
@@ -585,7 +689,8 @@ class Message(object):
|
|
|
585
689
|
}
|
|
586
690
|
|
|
587
691
|
response = requests.post(
|
|
588
|
-
f"{self.instance.url}", headers=self.instance.headers, json=payload
|
|
692
|
+
f"{self.instance.url}", headers=self.instance.headers, json=payload
|
|
693
|
+
)
|
|
589
694
|
if response.status_code == 200:
|
|
590
695
|
logging.info(response.json())
|
|
591
696
|
return response.json()
|
|
@@ -641,10 +746,17 @@ class Message(object):
|
|
|
641
746
|
return r.json()
|
|
642
747
|
|
|
643
748
|
|
|
644
|
-
|
|
645
|
-
class AsyncMessage(object):
|
|
749
|
+
class AsyncMessage:
|
|
646
750
|
# type: ignore
|
|
647
|
-
def __init__(
|
|
751
|
+
def __init__(
|
|
752
|
+
self,
|
|
753
|
+
id: int = None,
|
|
754
|
+
data: dict = {},
|
|
755
|
+
instance: WhatsApp = None,
|
|
756
|
+
content: str = "",
|
|
757
|
+
to: str = "",
|
|
758
|
+
rec_type: str = "individual",
|
|
759
|
+
):
|
|
648
760
|
self.instance = instance
|
|
649
761
|
self.url = self.instance.url
|
|
650
762
|
self.headers = self.instance.headers
|
|
@@ -661,8 +773,7 @@ class AsyncMessage(object):
|
|
|
661
773
|
self.rec = rec_type
|
|
662
774
|
self.to = to
|
|
663
775
|
try:
|
|
664
|
-
self.content = content if content != "" else self.instance.get_message(
|
|
665
|
-
data)
|
|
776
|
+
self.content = content if content != "" else self.instance.get_message(data)
|
|
666
777
|
except:
|
|
667
778
|
self.content = content
|
|
668
779
|
try:
|
|
@@ -705,9 +816,10 @@ class AsyncMessage(object):
|
|
|
705
816
|
self.interactive = self.instance.get_interactive_response(data)
|
|
706
817
|
except:
|
|
707
818
|
pass
|
|
708
|
-
|
|
709
819
|
|
|
710
|
-
async def reply(
|
|
820
|
+
async def reply(
|
|
821
|
+
self, reply_text: str = "", preview_url: bool = True
|
|
822
|
+
) -> asyncio.Future:
|
|
711
823
|
if self.data == {}:
|
|
712
824
|
return {"error": "No data provided"}
|
|
713
825
|
author = self.instance.get_author(self.data)
|
|
@@ -720,21 +832,28 @@ class AsyncMessage(object):
|
|
|
720
832
|
"text": {"preview_url": preview_url, "body": reply_text},
|
|
721
833
|
}
|
|
722
834
|
logging.info(f"Replying to {self.id}")
|
|
835
|
+
|
|
723
836
|
async def call():
|
|
724
837
|
async with aiohttp.ClientSession() as session:
|
|
725
|
-
async with session.post(
|
|
838
|
+
async with session.post(
|
|
839
|
+
self.url, headers=self.headers, json=payload
|
|
840
|
+
) as response:
|
|
726
841
|
if response.status == 200:
|
|
727
|
-
logging.info(
|
|
842
|
+
logging.info(
|
|
843
|
+
f"Message sent to {self.instance.get_author(self.data)}"
|
|
844
|
+
)
|
|
728
845
|
return await response.json()
|
|
729
|
-
logging.info(
|
|
846
|
+
logging.info(
|
|
847
|
+
f"Message not sent to {self.instance.get_author(self.data)}"
|
|
848
|
+
)
|
|
730
849
|
logging.info(f"Status code: {response.status}")
|
|
731
850
|
logging.error(f"Response: {await response.json()}")
|
|
732
851
|
return await response.json()
|
|
852
|
+
|
|
733
853
|
f = asyncio.ensure_future(call())
|
|
734
|
-
await asyncio.sleep(.001)
|
|
854
|
+
await asyncio.sleep(0.001) # make asyncio run the task
|
|
735
855
|
return f
|
|
736
|
-
|
|
737
|
-
|
|
856
|
+
|
|
738
857
|
async def mark_as_read(self) -> asyncio.Future:
|
|
739
858
|
|
|
740
859
|
payload = {
|
|
@@ -742,19 +861,23 @@ class AsyncMessage(object):
|
|
|
742
861
|
"status": "read",
|
|
743
862
|
"message_id": self.id,
|
|
744
863
|
}
|
|
864
|
+
|
|
745
865
|
async def call():
|
|
746
866
|
async with aiohttp.ClientSession() as session:
|
|
747
|
-
async with session.post(
|
|
867
|
+
async with session.post(
|
|
868
|
+
f"{self.instance.url}", headers=self.instance.headers, json=payload
|
|
869
|
+
) as response:
|
|
748
870
|
if response.status == 200:
|
|
749
871
|
logging.info(await response.json())
|
|
750
872
|
return await response.json()
|
|
751
873
|
else:
|
|
752
874
|
logging.error(await response.json())
|
|
753
875
|
return await response.json()
|
|
876
|
+
|
|
754
877
|
f = asyncio.ensure_future(call())
|
|
755
|
-
await asyncio.sleep(.001)
|
|
878
|
+
await asyncio.sleep(0.001) # make asyncio run the task
|
|
756
879
|
return f
|
|
757
|
-
|
|
880
|
+
|
|
758
881
|
async def send(self, sender=None, preview_url: bool = True) -> asyncio.Future:
|
|
759
882
|
try:
|
|
760
883
|
sender = dict(self.instance.l)[sender]
|
|
@@ -774,10 +897,13 @@ class AsyncMessage(object):
|
|
|
774
897
|
"text": {"preview_url": preview_url, "body": self.content},
|
|
775
898
|
}
|
|
776
899
|
logging.info(f"Sending message to {self.to}")
|
|
900
|
+
|
|
777
901
|
async def call():
|
|
778
902
|
print("sending")
|
|
779
903
|
async with aiohttp.ClientSession() as session:
|
|
780
|
-
async with session.post(
|
|
904
|
+
async with session.post(
|
|
905
|
+
url, headers=self.headers, json=data
|
|
906
|
+
) as response:
|
|
781
907
|
if response.status == 200:
|
|
782
908
|
logging.info(f"Message sent to {self.to}")
|
|
783
909
|
return await response.json()
|
|
@@ -785,10 +911,11 @@ class AsyncMessage(object):
|
|
|
785
911
|
logging.info(f"Status code: {response.status}")
|
|
786
912
|
logging.error(f"Response: {await response.json()}")
|
|
787
913
|
return await response.json()
|
|
914
|
+
|
|
788
915
|
f = asyncio.ensure_future(call())
|
|
789
|
-
await asyncio.sleep(.001)
|
|
916
|
+
await asyncio.sleep(0.001) # make asyncio run the task
|
|
790
917
|
return f
|
|
791
|
-
|
|
918
|
+
|
|
792
919
|
async def react(self, emoji: str) -> asyncio.Future:
|
|
793
920
|
data = {
|
|
794
921
|
"messaging_product": "whatsapp",
|
|
@@ -798,9 +925,12 @@ class AsyncMessage(object):
|
|
|
798
925
|
"reaction": {"message_id": self.id, "emoji": emoji},
|
|
799
926
|
}
|
|
800
927
|
logging.info(f"Reacting to {self.id}")
|
|
928
|
+
|
|
801
929
|
async def call():
|
|
802
930
|
async with aiohttp.ClientSession() as session:
|
|
803
|
-
async with session.post(
|
|
931
|
+
async with session.post(
|
|
932
|
+
self.url, headers=self.headers, json=data
|
|
933
|
+
) as response:
|
|
804
934
|
if response.status == 200:
|
|
805
935
|
logging.info(f"Reaction sent to {self.to}")
|
|
806
936
|
return await response.json()
|
|
@@ -808,6 +938,7 @@ class AsyncMessage(object):
|
|
|
808
938
|
logging.info(f"Status code: {response.status}")
|
|
809
939
|
logging.debug(f"Response: {await response.json()}")
|
|
810
940
|
return await response.json()
|
|
941
|
+
|
|
811
942
|
f = asyncio.ensure_future(call())
|
|
812
|
-
await asyncio.sleep(.001)
|
|
943
|
+
await asyncio.sleep(0.001)
|
|
813
944
|
return f
|
whatsapp/async_ext/_buttons.py
CHANGED
|
@@ -25,7 +25,9 @@ def create_button(self, button: Dict[Any, Any]) -> Dict[Any, Any]:
|
|
|
25
25
|
return data
|
|
26
26
|
|
|
27
27
|
|
|
28
|
-
async def send_button(
|
|
28
|
+
async def send_button(
|
|
29
|
+
self, button: Dict[Any, Any], recipient_id: str, sender=None
|
|
30
|
+
) -> asyncio.Future:
|
|
29
31
|
"""
|
|
30
32
|
Sends an interactive buttons message to a WhatsApp user
|
|
31
33
|
|
|
@@ -52,6 +54,7 @@ async def send_button(self, button: Dict[Any, Any], recipient_id: str, sender=No
|
|
|
52
54
|
"interactive": self.create_button(button),
|
|
53
55
|
}
|
|
54
56
|
logging.info(f"Sending buttons to {recipient_id}")
|
|
57
|
+
|
|
55
58
|
async def call():
|
|
56
59
|
async with aiohttp.ClientSession() as session:
|
|
57
60
|
async with session.post(url, headers=self.headers, json=data) as r:
|
|
@@ -62,10 +65,10 @@ async def send_button(self, button: Dict[Any, Any], recipient_id: str, sender=No
|
|
|
62
65
|
logging.info(f"Status code: {r.status}")
|
|
63
66
|
logging.info(f"Response: {await r.json()}")
|
|
64
67
|
return await r.json()
|
|
68
|
+
|
|
65
69
|
f = asyncio.ensure_future(call())
|
|
66
|
-
await asyncio.sleep(.001)
|
|
70
|
+
await asyncio.sleep(0.001) # make asyncio run the task
|
|
67
71
|
return f
|
|
68
|
-
|
|
69
72
|
|
|
70
73
|
|
|
71
74
|
async def send_reply_button(
|
|
@@ -102,6 +105,7 @@ async def send_reply_button(
|
|
|
102
105
|
"interactive": button,
|
|
103
106
|
}
|
|
104
107
|
logging.info(f"Sending buttons to {recipient_id}")
|
|
108
|
+
|
|
105
109
|
async def call():
|
|
106
110
|
async with aiohttp.ClientSession() as session:
|
|
107
111
|
async with session.post(url, headers=self.headers, json=data) as r:
|
|
@@ -112,7 +116,7 @@ async def send_reply_button(
|
|
|
112
116
|
logging.info(f"Status code: {r.status}")
|
|
113
117
|
logging.info(f"Response: {await r.json()}")
|
|
114
118
|
return await r.json()
|
|
115
|
-
|
|
119
|
+
|
|
116
120
|
f = asyncio.ensure_future(call())
|
|
117
|
-
await asyncio.sleep(.001)
|
|
121
|
+
await asyncio.sleep(0.001) # make asyncio run the task
|
|
118
122
|
return f
|