whatsapp-python 4.0.0__py3-none-any.whl → 4.0.2__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 CHANGED
@@ -1,399 +1,399 @@
1
- """
2
- Unofficial Python wrapper for the WhatsApp Cloud API.
3
- """
4
- from __future__ import annotations
5
-
6
- import requests
7
- import logging
8
- from bs4 import BeautifulSoup
9
- from fastapi import FastAPI, HTTPException, Request
10
- from uvicorn import run as _run
11
- from .constants import VERSION
12
- from .ext._property import authorized
13
- from .ext._send_others import send_custom_json, send_contacts
14
- from .ext._message import send_template
15
- from .ext._send_media import send_image, send_video, send_audio, send_location, send_sticker, send_document
16
- from .ext._media import upload_media, query_media_url, download_media, delete_media
17
- from .ext._buttons import send_button, create_button, send_reply_button
18
- from .ext._static import is_message, get_mobile, get_author, get_name, get_message, get_message_id, get_message_type, get_message_timestamp, get_audio, get_delivery, get_document, get_image, get_sticker, get_interactive_response, get_location, get_video, changed_field
19
- import json
20
-
21
- class WhatsApp(object):
22
- def __init__(self, token: str = "", phone_number_id: dict = "", logger: bool = True, update_check: bool = True, verify_token: str = "", debug: bool = True, version: str = "latest"):
23
- """
24
- Initialize the WhatsApp Object
25
-
26
- Args:
27
- token[str]: Token for the WhatsApp cloud API obtained from the Facebook developer portal
28
- phone_number_id[str]: Phone number id for the WhatsApp cloud API obtained from the developer portal
29
- logger[bool]: Whether to enable logging or not (default: True)
30
- """
31
-
32
- # Check if the version is up to date
33
- logging.getLogger(__name__).addHandler(logging.NullHandler())
34
-
35
- self.l = phone_number_id
36
-
37
- if isinstance(phone_number_id, dict):
38
- # use first phone number id as default
39
- phone_number_id = phone_number_id[list(phone_number_id.keys())[0]]
40
-
41
- elif phone_number_id == "":
42
- logging.error("Phone number ID not provided")
43
- raise ValueError(
44
- "Phone number ID not provided but required")
45
- elif isinstance(phone_number_id, str):
46
- logging.critical(
47
- "The phone number ID should be a dictionary of phone numbers and their IDs. Using strings is deprecated.")
48
- raise ValueError(
49
- "Phone number ID should be a dictionary of phone numbers and their IDs")
50
- else:
51
- pass
52
-
53
- self.VERSION = VERSION #package version
54
- r = requests.get("https://developers.facebook.com/docs/graph-api/changelog/").text
55
-
56
- ## dynamically get the latest version of the API
57
- if version == "latest":
58
- soup = BeautifulSoup(r, features="html.parser")
59
- t1 = soup.findAll("table")
60
- def makeversion(table):
61
- result = []
62
- allrows = table.findAll('tr')
63
- for row in allrows:
64
- result.append([])
65
- allcols = row.findAll('td')
66
- for col in allcols:
67
- thestrings = [(s) for s in col.findAll(text=True)]
68
- thetext = ''.join(thestrings)
69
- result[-1].append(thetext)
70
- return result[0][1]
71
- self.LATEST = makeversion(t1[0]) # latest version of the API
72
- else:
73
- self.LATEST = version
74
-
75
- if update_check is True:
76
- latest = str(requests.get(
77
- "https://pypi.org/pypi/whatsapp-python/json").json()["info"]["version"])
78
- if self.VERSION != latest:
79
- try:
80
- version_int = int(self.VERSION.replace(".", ""))
81
- except:
82
- version_int = 0
83
- try: latest_int = int(latest.replace(".", ""))
84
- except: latest_int = 0
85
- # this is to avoid the case where the version is 1.0.10 and the latest is 1.0.2 (possible if user is using the github version)
86
- if version_int < latest_int:
87
- if version_int == 0:
88
- logging.critical(
89
- 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.")
90
- else:
91
- logging.critical(
92
- 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.")
93
-
94
- if token == "":
95
- logging.error("Token not provided")
96
- raise ValueError("Token not provided but required")
97
- if phone_number_id == "":
98
- logging.error("Phone number ID not provided")
99
- raise ValueError(
100
- "Phone number ID not provided but required")
101
- self.token = token
102
- self.phone_number_id = phone_number_id
103
- self.base_url = "https://graph.facebook.com/v{self.LATEST}"
104
- self.url = f"{self.base_url}/{phone_number_id}/messages"
105
- self.verify_token = verify_token
106
-
107
- async def base(*args):
108
- pass
109
- self.message_handler = base
110
- self.other_handler = base
111
- self.verification_handler = base
112
- self.headers = {
113
- "Content-Type": "application/json",
114
- "Authorization": f"Bearer {self.token}"
115
- }
116
- if logger is False:
117
- logging.disable(logging.INFO)
118
- logging.disable(logging.ERROR)
119
- if debug is False:
120
- logging.disable(logging.DEBUG)
121
- logging.disable(logging.ERROR)
122
-
123
- self.app = FastAPI()
124
-
125
- # Verification handler has 1 argument: challenge (str | bool): str if verification is successful, False if not
126
-
127
- @self.app.get("/")
128
- async def verify_endpoint(r: Request):
129
- if r.query_params.get("hub.verify_token") == self.verify_token:
130
- logging.debug("Webhook verified successfully")
131
- challenge = r.query_params.get("hub.challenge")
132
- self.verification_handler(challenge)
133
- self.other_handler(challenge)
134
- return int(challenge)
135
- logging.error("Webhook Verification failed - token mismatch")
136
- await self.verification_handler(False)
137
- await self.other_handler(False)
138
- return {"success": False}
139
-
140
- @self.app.post("/")
141
- async def hook(r: Request):
142
- try:
143
- # Handle Webhook Subscriptions
144
- data = await r.json()
145
- if data is None:
146
- return {"success": False}
147
- data_str = json.dumps(data, indent=4)
148
- # log the data received only if the log level is debug
149
- logging.debug(f"Received webhook data: {data_str}")
150
-
151
- changed_field = self.changed_field(data)
152
- if changed_field == "messages":
153
- new_message = self.is_message(data)
154
- if new_message:
155
- msg = Message(instance=self, data=data)
156
- await self.message_handler(msg)
157
- await self.other_handler(msg)
158
- return {"success": True}
159
- except Exception as e:
160
- logging.error(f"Error parsing message: {e}")
161
- raise HTTPException(status_code=500, detail={
162
- "success": False,
163
- "error": str(e)
164
- })
165
-
166
- # all the files starting with _ are imported here, and should not be imported directly.
167
-
168
- is_message = staticmethod(is_message)
169
- get_mobile = staticmethod(get_mobile)
170
- get_name = staticmethod(get_name)
171
- get_message = staticmethod(get_message)
172
- get_message_id = staticmethod(get_message_id)
173
- get_message_type = staticmethod(get_message_type)
174
- get_message_timestamp = staticmethod(get_message_timestamp)
175
- get_audio = staticmethod(get_audio)
176
- get_delivery = staticmethod(get_delivery)
177
- get_document = staticmethod(get_document)
178
- get_image = staticmethod(get_image)
179
- get_sticker = staticmethod(get_sticker)
180
- get_interactive_response = staticmethod(get_interactive_response)
181
- get_location = staticmethod(get_location)
182
- get_video = staticmethod(get_video)
183
- changed_field = staticmethod(changed_field)
184
- get_author = staticmethod(get_author)
185
-
186
- send_button = send_button
187
- create_button = create_button
188
- send_reply_button = send_reply_button
189
- send_image = send_image
190
- send_video = send_video
191
- send_audio = send_audio
192
- send_location = send_location
193
- send_sticker = send_sticker
194
- send_document = send_document
195
- upload_media = upload_media
196
- query_media_url = query_media_url
197
- download_media = download_media
198
- delete_media = delete_media
199
- send_template = send_template
200
- send_custom_json = send_custom_json
201
- send_contacts = send_contacts
202
-
203
- authorized = property(authorized)
204
-
205
- def create_message(self, **kwargs) -> Message:
206
- """
207
- Create a message object
208
-
209
- Args:
210
- data[dict]: The message data
211
- content[str]: The message content
212
- to[str]: The recipient
213
- rec_type[str]: The recipient type (individual/group)
214
- """
215
- return Message(**kwargs, instance=self)
216
-
217
- def on_message(self, handler: function):
218
- """
219
- Set the handler for incoming messages
220
-
221
- Args:
222
- handler[function]: The handler function
223
- """
224
- self.message_handler = handler
225
-
226
- def on_event(self, handler: function):
227
- """
228
- Set the handler for other events
229
-
230
- Args:
231
- handler[function]: The handler function
232
- """
233
- self.other_handler = handler
234
-
235
- def on_verification(self, handler: function):
236
- """
237
- Set the handler for verification
238
-
239
- Args:
240
- handler[function]: The handler function
241
- """
242
- self.verification_handler = handler
243
-
244
- def run(self, host: str = "localhost", port: int = 5000, **options):
245
- _run(self.app, host=host, port=port, **options)
246
-
247
-
248
- class Message(object):
249
- # type: ignore
250
- def __init__(self, id: int = None, data: dict = {}, instance: WhatsApp = None, content: str = "", to: str = "", rec_type: str = "individual"):
251
- self.instance = instance
252
- self.url = self.instance.url
253
- self.headers = self.instance.headers
254
-
255
-
256
- try:
257
- self.id = instance.get_message_id(data)
258
- except:
259
- self.id = id
260
- try:
261
- self.type = self.instance.get_message_type(data)
262
- except:
263
- self.type = "text"
264
- self.data = data
265
- self.rec = rec_type
266
- self.to = to
267
- try:
268
- self.content = content if content != "" else self.instance.get_message(
269
- data)
270
- except:
271
- self.content = content
272
- try:
273
- self.name = self.instance.get_name(data)
274
- except:
275
- self.name = None
276
-
277
- if self.type == "image":
278
- try:
279
- self.image = self.instance.get_image(data)
280
- except:
281
- self.image = None
282
- if self.type == "sticker":
283
- try:
284
- self.sticker = self.instance.get_sticker(data)
285
- except:
286
- self.sticker = None
287
- elif self.type == "video":
288
- try:
289
- self.video = self.instance.get_video(data)
290
- except:
291
- self.video = None
292
- elif self.type == "audio":
293
- try:
294
- self.audio = self.instance.get_audio(data)
295
- except:
296
- pass
297
- elif self.type == "document":
298
- try:
299
- self.document = self.instance.get_document(data)
300
- except:
301
- pass
302
- elif self.type == "location":
303
- try:
304
- self.location = self.instance.get_location(data)
305
- except:
306
- pass
307
- elif self.type == "interactive":
308
- try:
309
- self.interactive = self.instance.get_interactive_response(data)
310
- except:
311
- pass
312
-
313
- def reply(self, reply_text: str = "", preview_url: bool = True) -> dict:
314
- if self.data == {}:
315
- return {"error": "No data provided"}
316
- author = self.instance.get_author(self.data)
317
- payload = {
318
- "messaging_product": "whatsapp",
319
- "recipient_type": "individual",
320
- "to": str(author),
321
- "type": "text",
322
- "context": {"message_id": self.id},
323
- "text": {"preview_url": preview_url, "body": reply_text},
324
- }
325
- logging.info(f"Replying to {self.id}")
326
- r = requests.post(self.url, headers=self.headers, json=payload)
327
- if r.status_code == 200:
328
- logging.info(f"Message sent to {self.instance.get_author(self.data)}")
329
- return r.json()
330
- logging.info(f"Message not sent to {self.instance.get_author(self.data)}")
331
- logging.info(f"Status code: {r.status_code}")
332
- logging.error(f"Response: {r.json()}")
333
- return r.json()
334
-
335
- def mark_as_read(self) -> dict:
336
-
337
- payload = {
338
- "messaging_product": "whatsapp",
339
- "status": "read",
340
- "message_id": self.id,
341
- }
342
-
343
- response = requests.post(
344
- f"{self.instance.url}", headers=self.instance.headers, json=payload)
345
- if response.status_code == 200:
346
- logging.info(response.json())
347
- return response.json()
348
- else:
349
- logging.error(response.json())
350
- return response.json()
351
-
352
- def send(self,sender = None, preview_url: bool = True) -> dict:
353
-
354
- try:
355
- sender = dict(self.instance.l)[sender]
356
-
357
-
358
-
359
- except:
360
- sender = self.instance.phone_number_id
361
-
362
- if sender == None:
363
- sender = self.instance.phone_number_id
364
-
365
- url = f"https://graph.facebook.com/v{self.instance.LATEST}/{sender}/messages"
366
- data = {
367
- "messaging_product": "whatsapp",
368
- "recipient_type": self.rec,
369
- "to": self.to,
370
- "type": "text",
371
- "text": {"preview_url": preview_url, "body": self.content},
372
- }
373
- logging.info(f"Sending message to {self.to}")
374
- r = requests.post(url, headers=self.headers, json=data)
375
- if r.status_code == 200:
376
- logging.info(f"Message sent to {self.to}")
377
- return r.json()
378
- logging.info(f"Message not sent to {self.to}")
379
- logging.info(f"Status code: {r.status_code}")
380
- logging.error(f"Response: {r.json()}")
381
- return r.json()
382
-
383
- def react(self, emoji: str) -> dict:
384
- data = {
385
- "messaging_product": "whatsapp",
386
- "recipient_type": "individual",
387
- "to": self.to,
388
- "type": "reaction",
389
- "reaction": {"message_id": self.id, "emoji": emoji},
390
- }
391
- logging.info(f"Reacting to {self.id}")
392
- r = requests.post(self.url, headers=self.headers, json=data)
393
- if r.status_code == 200:
394
- logging.info(f"Reaction sent to {self.to}")
395
- return r.json()
396
- logging.info(f"Reaction not sent to {self.to}")
397
- logging.info(f"Status code: {r.status_code}")
398
- logging.debug(f"Response: {r.json()}")
399
- return r.json()
1
+ """
2
+ Unofficial Python wrapper for the WhatsApp Cloud API.
3
+ """
4
+ from __future__ import annotations
5
+ import requests
6
+ import logging
7
+ from bs4 import BeautifulSoup
8
+ from fastapi import FastAPI, HTTPException, Request
9
+ from uvicorn import run as _run
10
+ from .constants import VERSION
11
+ from .ext._property import authorized
12
+ from .ext._send_others import send_custom_json, send_contacts
13
+ from .ext._message import send_template
14
+ from .ext._send_media import send_image, send_video, send_audio, send_location, send_sticker, send_document
15
+ from .ext._media import upload_media, query_media_url, download_media, delete_media
16
+ from .ext._buttons import send_button, create_button, send_reply_button
17
+ from .ext._static import is_message, get_mobile, get_author, get_name, get_message, get_message_id, get_message_type, get_message_timestamp, get_audio, get_delivery, get_document, get_image, get_sticker, get_interactive_response, get_location, get_video, changed_field
18
+ import json
19
+
20
+
21
+ class WhatsApp(object):
22
+ def __init__(self, token: str = "", phone_number_id: dict = "", logger: bool = True, update_check: bool = True, verify_token: str = "", debug: bool = True, version: str = "latest"):
23
+ """
24
+ Initialize the WhatsApp Object
25
+
26
+ Args:
27
+ token[str]: Token for the WhatsApp cloud API obtained from the Facebook developer portal
28
+ phone_number_id[str]: Phone number id for the WhatsApp cloud API obtained from the developer portal
29
+ logger[bool]: Whether to enable logging or not (default: True)
30
+ """
31
+
32
+ # Check if the version is up to date
33
+ logging.getLogger(__name__).addHandler(logging.NullHandler())
34
+
35
+ self.l = phone_number_id
36
+
37
+ if isinstance(phone_number_id, dict):
38
+ # use first phone number id as default
39
+ phone_number_id = phone_number_id[list(phone_number_id.keys())[0]]
40
+
41
+ elif phone_number_id == "":
42
+ logging.error("Phone number ID not provided")
43
+ raise ValueError(
44
+ "Phone number ID not provided but required")
45
+ elif isinstance(phone_number_id, str):
46
+ logging.critical(
47
+ "The phone number ID should be a dictionary of phone numbers and their IDs. Using strings is deprecated.")
48
+ raise ValueError(
49
+ "Phone number ID should be a dictionary of phone numbers and their IDs")
50
+ else:
51
+ pass
52
+
53
+ self.VERSION = VERSION # package version
54
+ r = requests.get("https://developers.facebook.com/docs/graph-api/changelog/").text
55
+
56
+ # dynamically get the latest version of the API
57
+ if version == "latest":
58
+ soup = BeautifulSoup(r, features="html.parser")
59
+ t1 = soup.findAll("table")
60
+
61
+ def makeversion(table):
62
+ result = []
63
+ allrows = table.findAll('tr')
64
+ for row in allrows:
65
+ result.append([])
66
+ allcols = row.findAll('td')
67
+ for col in allcols:
68
+ thestrings = [(s) for s in col.findAll(text=True)]
69
+ thetext = ''.join(thestrings)
70
+ result[-1].append(thetext)
71
+ return result[0][1]
72
+ self.LATEST = makeversion(t1[0]) # latest version of the API
73
+ else:
74
+ self.LATEST = version
75
+
76
+ if update_check is True:
77
+ latest = str(requests.get(
78
+ "https://pypi.org/pypi/whatsapp-python/json").json()["info"]["version"])
79
+ if self.VERSION != latest:
80
+ try:
81
+ version_int = int(self.VERSION.replace(".", ""))
82
+ except:
83
+ version_int = 0
84
+ try:
85
+ latest_int = int(latest.replace(".", ""))
86
+ except:
87
+ latest_int = 0
88
+ # this is to avoid the case where the version is 1.0.10 and the latest is 1.0.2 (possible if user is using the github version)
89
+ if version_int < latest_int:
90
+ if version_int == 0:
91
+ logging.critical(
92
+ 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.")
93
+ else:
94
+ logging.critical(
95
+ 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.")
96
+
97
+ if token == "":
98
+ logging.error("Token not provided")
99
+ raise ValueError("Token not provided but required")
100
+ if phone_number_id == "":
101
+ logging.error("Phone number ID not provided")
102
+ raise ValueError(
103
+ "Phone number ID not provided but required")
104
+ self.token = token
105
+ self.phone_number_id = phone_number_id
106
+ self.base_url = f"https://graph.facebook.com/{self.LATEST}"
107
+ self.url = f"{self.base_url}/{phone_number_id}/messages"
108
+ self.verify_token = verify_token
109
+
110
+ async def base(*args):
111
+ pass
112
+ self.message_handler = base
113
+ self.other_handler = base
114
+ self.verification_handler = base
115
+ self.headers = {
116
+ "Content-Type": "application/json",
117
+ "Authorization": f"Bearer {self.token}"
118
+ }
119
+ if logger is False:
120
+ logging.disable(logging.INFO)
121
+ logging.disable(logging.ERROR)
122
+ if debug is False:
123
+ logging.disable(logging.DEBUG)
124
+ logging.disable(logging.ERROR)
125
+
126
+ self.app = FastAPI()
127
+
128
+ # Verification handler has 1 argument: challenge (str | bool): str if verification is successful, False if not
129
+
130
+ @self.app.get("/")
131
+ async def verify_endpoint(r: Request):
132
+ if r.query_params.get("hub.verify_token") == self.verify_token:
133
+ logging.debug("Webhook verified successfully")
134
+ challenge = r.query_params.get("hub.challenge")
135
+ self.verification_handler(challenge)
136
+ self.other_handler(challenge)
137
+ return int(challenge)
138
+ logging.error("Webhook Verification failed - token mismatch")
139
+ await self.verification_handler(False)
140
+ await self.other_handler(False)
141
+ return {"success": False}
142
+
143
+ @self.app.post("/")
144
+ async def hook(r: Request):
145
+ try:
146
+ # Handle Webhook Subscriptions
147
+ data = await r.json()
148
+ if data is None:
149
+ return {"success": False}
150
+ data_str = json.dumps(data, indent=4)
151
+ # log the data received only if the log level is debug
152
+ logging.debug(f"Received webhook data: {data_str}")
153
+
154
+ changed_field = self.changed_field(data)
155
+ if changed_field == "messages":
156
+ new_message = self.is_message(data)
157
+ if new_message:
158
+ msg = Message(instance=self, data=data)
159
+ await self.message_handler(msg)
160
+ await self.other_handler(msg)
161
+ return {"success": True}
162
+ except Exception as e:
163
+ logging.error(f"Error parsing message: {e}")
164
+ raise HTTPException(status_code=500, detail={
165
+ "success": False,
166
+ "error": str(e)
167
+ })
168
+
169
+ # all the files starting with _ are imported here, and should not be imported directly.
170
+
171
+ is_message = staticmethod(is_message)
172
+ get_mobile = staticmethod(get_mobile)
173
+ get_name = staticmethod(get_name)
174
+ get_message = staticmethod(get_message)
175
+ get_message_id = staticmethod(get_message_id)
176
+ get_message_type = staticmethod(get_message_type)
177
+ get_message_timestamp = staticmethod(get_message_timestamp)
178
+ get_audio = staticmethod(get_audio)
179
+ get_delivery = staticmethod(get_delivery)
180
+ get_document = staticmethod(get_document)
181
+ get_image = staticmethod(get_image)
182
+ get_sticker = staticmethod(get_sticker)
183
+ get_interactive_response = staticmethod(get_interactive_response)
184
+ get_location = staticmethod(get_location)
185
+ get_video = staticmethod(get_video)
186
+ changed_field = staticmethod(changed_field)
187
+ get_author = staticmethod(get_author)
188
+
189
+ send_button = send_button
190
+ create_button = create_button
191
+ send_reply_button = send_reply_button
192
+ send_image = send_image
193
+ send_video = send_video
194
+ send_audio = send_audio
195
+ send_location = send_location
196
+ send_sticker = send_sticker
197
+ send_document = send_document
198
+ upload_media = upload_media
199
+ query_media_url = query_media_url
200
+ download_media = download_media
201
+ delete_media = delete_media
202
+ send_template = send_template
203
+ send_custom_json = send_custom_json
204
+ send_contacts = send_contacts
205
+
206
+ authorized = property(authorized)
207
+
208
+ def create_message(self, **kwargs) -> Message:
209
+ """
210
+ Create a message object
211
+
212
+ Args:
213
+ data[dict]: The message data
214
+ content[str]: The message content
215
+ to[str]: The recipient
216
+ rec_type[str]: The recipient type (individual/group)
217
+ """
218
+ return Message(**kwargs, instance=self)
219
+
220
+ def on_message(self, handler: function):
221
+ """
222
+ Set the handler for incoming messages
223
+
224
+ Args:
225
+ handler[function]: The handler function
226
+ """
227
+ self.message_handler = handler
228
+
229
+ def on_event(self, handler: function):
230
+ """
231
+ Set the handler for other events
232
+
233
+ Args:
234
+ handler[function]: The handler function
235
+ """
236
+ self.other_handler = handler
237
+
238
+ def on_verification(self, handler: function):
239
+ """
240
+ Set the handler for verification
241
+
242
+ Args:
243
+ handler[function]: The handler function
244
+ """
245
+ self.verification_handler = handler
246
+
247
+ def run(self, host: str = "localhost", port: int = 5000, **options):
248
+ _run(self.app, host=host, port=port, **options)
249
+
250
+
251
+ class Message(object):
252
+ # type: ignore
253
+ def __init__(self, id: int = None, data: dict = {}, instance: WhatsApp = None, content: str = "", to: str = "", rec_type: str = "individual"):
254
+ self.instance = instance
255
+ self.url = self.instance.url
256
+ self.headers = self.instance.headers
257
+
258
+ try:
259
+ self.id = instance.get_message_id(data)
260
+ except:
261
+ self.id = id
262
+ try:
263
+ self.type = self.instance.get_message_type(data)
264
+ except:
265
+ self.type = "text"
266
+ self.data = data
267
+ self.rec = rec_type
268
+ self.to = to
269
+ try:
270
+ self.content = content if content != "" else self.instance.get_message(
271
+ data)
272
+ except:
273
+ self.content = content
274
+ try:
275
+ self.name = self.instance.get_name(data)
276
+ except:
277
+ self.name = None
278
+
279
+ if self.type == "image":
280
+ try:
281
+ self.image = self.instance.get_image(data)
282
+ except:
283
+ self.image = None
284
+ if self.type == "sticker":
285
+ try:
286
+ self.sticker = self.instance.get_sticker(data)
287
+ except:
288
+ self.sticker = None
289
+ elif self.type == "video":
290
+ try:
291
+ self.video = self.instance.get_video(data)
292
+ except:
293
+ self.video = None
294
+ elif self.type == "audio":
295
+ try:
296
+ self.audio = self.instance.get_audio(data)
297
+ except:
298
+ pass
299
+ elif self.type == "document":
300
+ try:
301
+ self.document = self.instance.get_document(data)
302
+ except:
303
+ pass
304
+ elif self.type == "location":
305
+ try:
306
+ self.location = self.instance.get_location(data)
307
+ except:
308
+ pass
309
+ elif self.type == "interactive":
310
+ try:
311
+ self.interactive = self.instance.get_interactive_response(data)
312
+ except:
313
+ pass
314
+
315
+ def reply(self, reply_text: str = "", preview_url: bool = True) -> dict:
316
+ if self.data == {}:
317
+ return {"error": "No data provided"}
318
+ author = self.instance.get_author(self.data)
319
+ payload = {
320
+ "messaging_product": "whatsapp",
321
+ "recipient_type": "individual",
322
+ "to": str(author),
323
+ "type": "text",
324
+ "context": {"message_id": self.id},
325
+ "text": {"preview_url": preview_url, "body": reply_text},
326
+ }
327
+ logging.info(f"Replying to {self.id}")
328
+ r = requests.post(self.url, headers=self.headers, json=payload)
329
+ if r.status_code == 200:
330
+ logging.info(f"Message sent to {self.instance.get_author(self.data)}")
331
+ return r.json()
332
+ logging.info(f"Message not sent to {self.instance.get_author(self.data)}")
333
+ logging.info(f"Status code: {r.status_code}")
334
+ logging.error(f"Response: {r.json()}")
335
+ return r.json()
336
+
337
+ def mark_as_read(self) -> dict:
338
+
339
+ payload = {
340
+ "messaging_product": "whatsapp",
341
+ "status": "read",
342
+ "message_id": self.id,
343
+ }
344
+
345
+ response = requests.post(
346
+ f"{self.instance.url}", headers=self.instance.headers, json=payload)
347
+ if response.status_code == 200:
348
+ logging.info(response.json())
349
+ return response.json()
350
+ else:
351
+ logging.error(response.json())
352
+ return response.json()
353
+
354
+ def send(self, sender=None, preview_url: bool = True) -> dict:
355
+
356
+ try:
357
+ sender = dict(self.instance.l)[sender]
358
+
359
+ except:
360
+ sender = self.instance.phone_number_id
361
+
362
+ if sender == None:
363
+ sender = self.instance.phone_number_id
364
+
365
+ url = f"https://graph.facebook.com/{self.instance.LATEST}/{sender}/messages"
366
+ data = {
367
+ "messaging_product": "whatsapp",
368
+ "recipient_type": self.rec,
369
+ "to": self.to,
370
+ "type": "text",
371
+ "text": {"preview_url": preview_url, "body": self.content},
372
+ }
373
+ logging.info(f"Sending message to {self.to}")
374
+ r = requests.post(url, headers=self.headers, json=data)
375
+ if r.status_code == 200:
376
+ logging.info(f"Message sent to {self.to}")
377
+ return r.json()
378
+ logging.info(f"Message not sent to {self.to}")
379
+ logging.info(f"Status code: {r.status_code}")
380
+ logging.error(f"Response: {r.json()}")
381
+ return r.json()
382
+
383
+ def react(self, emoji: str) -> dict:
384
+ data = {
385
+ "messaging_product": "whatsapp",
386
+ "recipient_type": "individual",
387
+ "to": self.to,
388
+ "type": "reaction",
389
+ "reaction": {"message_id": self.id, "emoji": emoji},
390
+ }
391
+ logging.info(f"Reacting to {self.id}")
392
+ r = requests.post(self.url, headers=self.headers, json=data)
393
+ if r.status_code == 200:
394
+ logging.info(f"Reaction sent to {self.to}")
395
+ return r.json()
396
+ logging.info(f"Reaction not sent to {self.to}")
397
+ logging.info(f"Status code: {r.status_code}")
398
+ logging.debug(f"Response: {r.json()}")
399
+ return r.json()