universal-mcp-applications 0.1.30rc2__py3-none-any.whl → 0.1.36rc2__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.
Files changed (105) hide show
  1. universal_mcp/applications/ahrefs/app.py +52 -198
  2. universal_mcp/applications/airtable/app.py +23 -122
  3. universal_mcp/applications/apollo/app.py +111 -464
  4. universal_mcp/applications/asana/app.py +417 -1567
  5. universal_mcp/applications/aws_s3/app.py +36 -103
  6. universal_mcp/applications/bill/app.py +546 -1957
  7. universal_mcp/applications/box/app.py +1068 -3981
  8. universal_mcp/applications/braze/app.py +364 -1430
  9. universal_mcp/applications/browser_use/app.py +2 -8
  10. universal_mcp/applications/cal_com_v2/app.py +207 -625
  11. universal_mcp/applications/calendly/app.py +61 -200
  12. universal_mcp/applications/canva/app.py +45 -110
  13. universal_mcp/applications/clickup/app.py +207 -674
  14. universal_mcp/applications/coda/app.py +146 -426
  15. universal_mcp/applications/confluence/app.py +310 -1098
  16. universal_mcp/applications/contentful/app.py +36 -151
  17. universal_mcp/applications/crustdata/app.py +28 -107
  18. universal_mcp/applications/dialpad/app.py +283 -756
  19. universal_mcp/applications/digitalocean/app.py +1766 -5777
  20. universal_mcp/applications/domain_checker/app.py +3 -54
  21. universal_mcp/applications/e2b/app.py +14 -64
  22. universal_mcp/applications/elevenlabs/app.py +9 -47
  23. universal_mcp/applications/exa/app.py +6 -17
  24. universal_mcp/applications/falai/app.py +24 -101
  25. universal_mcp/applications/figma/app.py +53 -137
  26. universal_mcp/applications/file_system/app.py +2 -13
  27. universal_mcp/applications/firecrawl/app.py +51 -152
  28. universal_mcp/applications/fireflies/app.py +59 -281
  29. universal_mcp/applications/fpl/app.py +91 -528
  30. universal_mcp/applications/fpl/utils/fixtures.py +15 -49
  31. universal_mcp/applications/fpl/utils/helper.py +25 -89
  32. universal_mcp/applications/fpl/utils/league_utils.py +20 -64
  33. universal_mcp/applications/ghost_content/app.py +52 -161
  34. universal_mcp/applications/github/app.py +19 -56
  35. universal_mcp/applications/gong/app.py +88 -248
  36. universal_mcp/applications/google_calendar/app.py +16 -68
  37. universal_mcp/applications/google_docs/app.py +88 -188
  38. universal_mcp/applications/google_drive/app.py +141 -463
  39. universal_mcp/applications/google_gemini/app.py +12 -64
  40. universal_mcp/applications/google_mail/app.py +28 -157
  41. universal_mcp/applications/google_searchconsole/app.py +15 -48
  42. universal_mcp/applications/google_sheet/app.py +103 -580
  43. universal_mcp/applications/google_sheet/helper.py +10 -37
  44. universal_mcp/applications/hashnode/app.py +57 -269
  45. universal_mcp/applications/heygen/app.py +44 -122
  46. universal_mcp/applications/http_tools/app.py +10 -32
  47. universal_mcp/applications/hubspot/api_segments/crm_api.py +460 -1573
  48. universal_mcp/applications/hubspot/api_segments/marketing_api.py +74 -262
  49. universal_mcp/applications/hubspot/app.py +23 -87
  50. universal_mcp/applications/jira/app.py +2071 -7986
  51. universal_mcp/applications/klaviyo/app.py +494 -1376
  52. universal_mcp/applications/linkedin/README.md +9 -2
  53. universal_mcp/applications/linkedin/app.py +392 -212
  54. universal_mcp/applications/mailchimp/app.py +450 -1605
  55. universal_mcp/applications/markitdown/app.py +8 -20
  56. universal_mcp/applications/miro/app.py +217 -699
  57. universal_mcp/applications/ms_teams/app.py +64 -186
  58. universal_mcp/applications/neon/app.py +86 -192
  59. universal_mcp/applications/notion/app.py +21 -36
  60. universal_mcp/applications/onedrive/app.py +16 -38
  61. universal_mcp/applications/openai/app.py +42 -165
  62. universal_mcp/applications/outlook/app.py +24 -84
  63. universal_mcp/applications/perplexity/app.py +4 -19
  64. universal_mcp/applications/pipedrive/app.py +832 -3142
  65. universal_mcp/applications/posthog/app.py +163 -432
  66. universal_mcp/applications/reddit/app.py +40 -139
  67. universal_mcp/applications/resend/app.py +41 -107
  68. universal_mcp/applications/retell/app.py +14 -41
  69. universal_mcp/applications/rocketlane/app.py +221 -934
  70. universal_mcp/applications/scraper/README.md +7 -4
  71. universal_mcp/applications/scraper/app.py +216 -102
  72. universal_mcp/applications/semanticscholar/app.py +22 -64
  73. universal_mcp/applications/semrush/app.py +43 -77
  74. universal_mcp/applications/sendgrid/app.py +512 -1262
  75. universal_mcp/applications/sentry/app.py +271 -906
  76. universal_mcp/applications/serpapi/app.py +40 -143
  77. universal_mcp/applications/sharepoint/app.py +17 -39
  78. universal_mcp/applications/shopify/app.py +1551 -4287
  79. universal_mcp/applications/shortcut/app.py +155 -417
  80. universal_mcp/applications/slack/app.py +50 -101
  81. universal_mcp/applications/spotify/app.py +126 -325
  82. universal_mcp/applications/supabase/app.py +104 -213
  83. universal_mcp/applications/tavily/app.py +1 -1
  84. universal_mcp/applications/trello/app.py +693 -2656
  85. universal_mcp/applications/twilio/app.py +14 -50
  86. universal_mcp/applications/twitter/api_segments/compliance_api.py +4 -14
  87. universal_mcp/applications/twitter/api_segments/dm_conversations_api.py +6 -18
  88. universal_mcp/applications/twitter/api_segments/likes_api.py +1 -3
  89. universal_mcp/applications/twitter/api_segments/lists_api.py +5 -15
  90. universal_mcp/applications/twitter/api_segments/trends_api.py +1 -3
  91. universal_mcp/applications/twitter/api_segments/tweets_api.py +9 -31
  92. universal_mcp/applications/twitter/api_segments/usage_api.py +1 -5
  93. universal_mcp/applications/twitter/api_segments/users_api.py +14 -42
  94. universal_mcp/applications/whatsapp/app.py +35 -186
  95. universal_mcp/applications/whatsapp/audio.py +2 -6
  96. universal_mcp/applications/whatsapp/whatsapp.py +17 -51
  97. universal_mcp/applications/whatsapp_business/app.py +70 -283
  98. universal_mcp/applications/wrike/app.py +45 -118
  99. universal_mcp/applications/yahoo_finance/app.py +19 -65
  100. universal_mcp/applications/youtube/app.py +75 -261
  101. universal_mcp/applications/zenquotes/app.py +2 -2
  102. {universal_mcp_applications-0.1.30rc2.dist-info → universal_mcp_applications-0.1.36rc2.dist-info}/METADATA +2 -2
  103. {universal_mcp_applications-0.1.30rc2.dist-info → universal_mcp_applications-0.1.36rc2.dist-info}/RECORD +105 -105
  104. {universal_mcp_applications-0.1.30rc2.dist-info → universal_mcp_applications-0.1.36rc2.dist-info}/WHEEL +0 -0
  105. {universal_mcp_applications-0.1.30rc2.dist-info → universal_mcp_applications-0.1.36rc2.dist-info}/licenses/LICENSE +0 -0
@@ -1,5 +1,4 @@
1
1
  from typing import Any
2
-
3
2
  from universal_mcp.applications.application import APIApplication
4
3
  from universal_mcp.integrations import Integration
5
4
 
@@ -9,9 +8,7 @@ class WhatsappBusinessApp(APIApplication):
9
8
  super().__init__(name="whatsapp_business", integration=integration, **kwargs)
10
9
  self.base_url = "https://graph.facebook.com"
11
10
 
12
- def get_whatsapp_business_account(
13
- self, api_version: str, waba_id: str, fields: str | None = None
14
- ) -> dict[str, Any]:
11
+ async def get_whatsapp_business_account(self, api_version: str, waba_id: str, fields: str | None = None) -> dict[str, Any]:
15
12
  """
16
13
  Fetches customizable data, primarily analytics, for a specific WhatsApp Business Account (WABA) using its ID. The `fields` parameter allows detailed queries, including date ranges and granularity for metrics like message volume, to refine the returned data.
17
14
 
@@ -38,20 +35,14 @@ class WhatsappBusinessApp(APIApplication):
38
35
  query_params = {k: v for k, v in [("fields", fields)] if v is not None}
39
36
  response = self._get(url, params=query_params)
40
37
  response.raise_for_status()
41
- if (
42
- response.status_code == 204
43
- or not response.content
44
- or not response.text.strip()
45
- ):
38
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
46
39
  return None
47
40
  try:
48
41
  return response.json()
49
42
  except ValueError:
50
43
  return None
51
44
 
52
- def get_business_account_credit_lines(
53
- self, api_version: str, business_account_id: str
54
- ) -> dict[str, Any]:
45
+ async def get_business_account_credit_lines(self, api_version: str, business_account_id: str) -> dict[str, Any]:
55
46
  """
56
47
  Retrieves the extended credit lines for a specified business account ID. This function fetches billing information by querying the `/extendedcredits` endpoint, returning financial details such as available credit for platform services.
57
48
 
@@ -77,20 +68,14 @@ class WhatsappBusinessApp(APIApplication):
77
68
  query_params = {}
78
69
  response = self._get(url, params=query_params)
79
70
  response.raise_for_status()
80
- if (
81
- response.status_code == 204
82
- or not response.content
83
- or not response.text.strip()
84
- ):
71
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
85
72
  return None
86
73
  try:
87
74
  return response.json()
88
75
  except ValueError:
89
76
  return None
90
77
 
91
- def get_business_account(
92
- self, api_version: str, business_account_id: str, fields: str | None = None
93
- ) -> dict[str, Any]:
78
+ async def get_business_account(self, api_version: str, business_account_id: str, fields: str | None = None) -> dict[str, Any]:
94
79
  """
95
80
  Fetches details for a specific Meta Business Account using its ID. This function retrieves the core account object, unlike others that get associated resources like owned/shared WhatsApp Business Accounts (WABAs) or credit lines for the same ID. The response payload can be customized using the 'fields' parameter.
96
81
 
@@ -117,20 +102,14 @@ class WhatsappBusinessApp(APIApplication):
117
102
  query_params = {k: v for k, v in [("fields", fields)] if v is not None}
118
103
  response = self._get(url, params=query_params)
119
104
  response.raise_for_status()
120
- if (
121
- response.status_code == 204
122
- or not response.content
123
- or not response.text.strip()
124
- ):
105
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
125
106
  return None
126
107
  try:
127
108
  return response.json()
128
109
  except ValueError:
129
110
  return None
130
111
 
131
- def get_commerce_settings(
132
- self, api_version: str, business_phone_number_id: str
133
- ) -> dict[str, Any]:
112
+ async def get_commerce_settings(self, api_version: str, business_phone_number_id: str) -> dict[str, Any]:
134
113
  """
135
114
  Retrieves the commerce settings, such as cart availability and catalog visibility, for a specific WhatsApp Business phone number. This function reads the current configuration, contrasting with `set_or_update_commerce_settings` which modifies them.
136
115
 
@@ -156,23 +135,15 @@ class WhatsappBusinessApp(APIApplication):
156
135
  query_params = {}
157
136
  response = self._get(url, params=query_params)
158
137
  response.raise_for_status()
159
- if (
160
- response.status_code == 204
161
- or not response.content
162
- or not response.text.strip()
163
- ):
138
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
164
139
  return None
165
140
  try:
166
141
  return response.json()
167
142
  except ValueError:
168
143
  return None
169
144
 
170
- def update_commerce_settings(
171
- self,
172
- api_version: str,
173
- business_phone_number_id: str,
174
- is_cart_enabled: str | None = None,
175
- is_catalog_visible: str | None = None,
145
+ async def update_commerce_settings(
146
+ self, api_version: str, business_phone_number_id: str, is_cart_enabled: str | None = None, is_catalog_visible: str | None = None
176
147
  ) -> dict[str, Any]:
177
148
  """
178
149
  Updates the commerce settings for a specific business phone number by enabling or disabling cart functionality and catalog visibility. This function differentiates from `get_commerce_settings` by using a POST request to modify data, rather than retrieving it.
@@ -200,37 +171,19 @@ class WhatsappBusinessApp(APIApplication):
200
171
  request_body_data = None
201
172
  url = f"{self.base_url}/{api_version}/{business_phone_number_id}/whatsapp_commerce_settings"
202
173
  query_params = {
203
- k: v
204
- for k, v in [
205
- ("is_cart_enabled", is_cart_enabled),
206
- ("is_catalog_visible", is_catalog_visible),
207
- ]
208
- if v is not None
174
+ k: v for k, v in [("is_cart_enabled", is_cart_enabled), ("is_catalog_visible", is_catalog_visible)] if v is not None
209
175
  }
210
- response = self._post(
211
- url,
212
- data=request_body_data,
213
- params=query_params,
214
- content_type="application/json",
215
- )
176
+ response = self._post(url, data=request_body_data, params=query_params, content_type="application/json")
216
177
  response.raise_for_status()
217
- if (
218
- response.status_code == 204
219
- or not response.content
220
- or not response.text.strip()
221
- ):
178
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
222
179
  return None
223
180
  try:
224
181
  return response.json()
225
182
  except ValueError:
226
183
  return None
227
184
 
228
- def create_upload_session(
229
- self,
230
- api_version: str,
231
- app_id: str,
232
- file_length: str | None = None,
233
- file_type: str | None = None,
185
+ async def create_upload_session(
186
+ self, api_version: str, app_id: str, file_length: str | None = None, file_type: str | None = None
234
187
  ) -> dict[str, Any]:
235
188
  """
236
189
  Initiates a resumable upload session by providing file metadata (size, type). This function creates an upload session ID and is the first of a two-step process for uploading media, preceding the actual data transfer performed by `resume_session`.
@@ -257,30 +210,17 @@ class WhatsappBusinessApp(APIApplication):
257
210
  raise ValueError("Missing required parameter 'app-id'.")
258
211
  request_body_data = None
259
212
  url = f"{self.base_url}/{api_version}/{app_id}/uploads"
260
- query_params = {
261
- k: v
262
- for k, v in [("file_length", file_length), ("file_type", file_type)]
263
- if v is not None
264
- }
265
- response = self._post(
266
- url,
267
- data=request_body_data,
268
- params=query_params,
269
- content_type="application/json",
270
- )
213
+ query_params = {k: v for k, v in [("file_length", file_length), ("file_type", file_type)] if v is not None}
214
+ response = self._post(url, data=request_body_data, params=query_params, content_type="application/json")
271
215
  response.raise_for_status()
272
- if (
273
- response.status_code == 204
274
- or not response.content
275
- or not response.text.strip()
276
- ):
216
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
277
217
  return None
278
218
  try:
279
219
  return response.json()
280
220
  except ValueError:
281
221
  return None
282
222
 
283
- def upload_file_to_session(self, api_version: str) -> dict[str, Any]:
223
+ async def upload_file_to_session(self, api_version: str) -> dict[str, Any]:
284
224
  """
285
225
  Continues a media file upload by sending file data to an existing session. This function is the second step in the upload process, following `upload_file`, which creates the session and provides the required session ID.
286
226
 
@@ -302,30 +242,16 @@ class WhatsappBusinessApp(APIApplication):
302
242
  request_body_data = None
303
243
  url = f"{self.base_url}/{api_version}/<SESSION_ID>"
304
244
  query_params = {}
305
- response = self._post(
306
- url,
307
- data=request_body_data,
308
- params=query_params,
309
- content_type="application/json",
310
- )
245
+ response = self._post(url, data=request_body_data, params=query_params, content_type="application/json")
311
246
  response.raise_for_status()
312
- if (
313
- response.status_code == 204
314
- or not response.content
315
- or not response.text.strip()
316
- ):
247
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
317
248
  return None
318
249
  try:
319
250
  return response.json()
320
251
  except ValueError:
321
252
  return None
322
253
 
323
- def get_business_phone_number(
324
- self,
325
- api_version: str,
326
- business_phone_number_id: str,
327
- fields: str | None = None,
328
- ) -> dict[str, Any]:
254
+ async def get_business_phone_number(self, api_version: str, business_phone_number_id: str, fields: str | None = None) -> dict[str, Any]:
329
255
  """
330
256
  Retrieves details for a specific WhatsApp Business phone number by its unique ID. The optional `fields` parameter allows for customizing the response to include only desired data, differentiating it from `get_all_business_phone_numbers`, which retrieves a list of all numbers for a WABA.
331
257
 
@@ -352,23 +278,15 @@ class WhatsappBusinessApp(APIApplication):
352
278
  query_params = {k: v for k, v in [("fields", fields)] if v is not None}
353
279
  response = self._get(url, params=query_params)
354
280
  response.raise_for_status()
355
- if (
356
- response.status_code == 204
357
- or not response.content
358
- or not response.text.strip()
359
- ):
281
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
360
282
  return None
361
283
  try:
362
284
  return response.json()
363
285
  except ValueError:
364
286
  return None
365
287
 
366
- def list_waba_phone_numbers(
367
- self,
368
- api_version: str,
369
- waba_id: str,
370
- fields: str | None = None,
371
- filtering: str | None = None,
288
+ async def list_waba_phone_numbers(
289
+ self, api_version: str, waba_id: str, fields: str | None = None, filtering: str | None = None
372
290
  ) -> list[Any]:
373
291
  """
374
292
  Fetches a list of phone numbers for a specified WhatsApp Business Account (WABA). This function allows for result filtering and customizable field selection, distinguishing it from `get_business_phone_number` which retrieves a single number by its unique ID.
@@ -394,27 +312,17 @@ class WhatsappBusinessApp(APIApplication):
394
312
  if waba_id is None:
395
313
  raise ValueError("Missing required parameter 'waba-id'.")
396
314
  url = f"{self.base_url}/{api_version}/{waba_id}/phone_numbers"
397
- query_params = {
398
- k: v
399
- for k, v in [("fields", fields), ("filtering", filtering)]
400
- if v is not None
401
- }
315
+ query_params = {k: v for k, v in [("fields", fields), ("filtering", filtering)] if v is not None}
402
316
  response = self._get(url, params=query_params)
403
317
  response.raise_for_status()
404
- if (
405
- response.status_code == 204
406
- or not response.content
407
- or not response.text.strip()
408
- ):
318
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
409
319
  return None
410
320
  try:
411
321
  return response.json()
412
322
  except ValueError:
413
323
  return None
414
324
 
415
- def get_qr_code_by_id(
416
- self, api_version: str, business_phone_number_id: str
417
- ) -> dict[str, Any]:
325
+ async def get_qr_code_by_id(self, api_version: str, business_phone_number_id: str) -> dict[str, Any]:
418
326
  """
419
327
  Retrieves the details of a single QR code, such as its pre-filled message, by its unique ID for a specific business phone number. It fetches a specific code, distinguishing it from `get_all_qr_codes_default_fields` which retrieves a list of codes.
420
328
 
@@ -440,20 +348,14 @@ class WhatsappBusinessApp(APIApplication):
440
348
  query_params = {}
441
349
  response = self._get(url, params=query_params)
442
350
  response.raise_for_status()
443
- if (
444
- response.status_code == 204
445
- or not response.content
446
- or not response.text.strip()
447
- ):
351
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
448
352
  return None
449
353
  try:
450
354
  return response.json()
451
355
  except ValueError:
452
356
  return None
453
357
 
454
- def delete_qr_code_by_id(
455
- self, api_version: str, business_phone_number_id: str
456
- ) -> dict[str, Any]:
358
+ async def delete_qr_code_by_id(self, api_version: str, business_phone_number_id: str) -> dict[str, Any]:
457
359
  """
458
360
  Deletes a specific WhatsApp message QR code by its ID for a given business phone number. The function sends a DELETE request to the Graph API's `message_qrdls` endpoint to remove the specified QR code.
459
361
 
@@ -479,23 +381,15 @@ class WhatsappBusinessApp(APIApplication):
479
381
  query_params = {}
480
382
  response = self._delete(url, params=query_params)
481
383
  response.raise_for_status()
482
- if (
483
- response.status_code == 204
484
- or not response.content
485
- or not response.text.strip()
486
- ):
384
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
487
385
  return None
488
386
  try:
489
387
  return response.json()
490
388
  except ValueError:
491
389
  return None
492
390
 
493
- def list_qr_codes(
494
- self,
495
- api_version: str,
496
- business_phone_number_id: str,
497
- fields: str | None = None,
498
- code: str | None = None,
391
+ async def list_qr_codes(
392
+ self, api_version: str, business_phone_number_id: str, fields: str | None = None, code: str | None = None
499
393
  ) -> dict[str, Any]:
500
394
  """
501
395
  Retrieves a list of QR codes for a business phone number. This function allows optional filtering by a specific QR code identifier and customization of the fields returned in the response, such as the image format.
@@ -521,28 +415,18 @@ class WhatsappBusinessApp(APIApplication):
521
415
  if business_phone_number_id is None:
522
416
  raise ValueError("Missing required parameter 'business-phone-number-id'.")
523
417
  url = f"{self.base_url}/{api_version}/{business_phone_number_id}/message_qrdls"
524
- query_params = {
525
- k: v for k, v in [("fields", fields), ("code", code)] if v is not None
526
- }
418
+ query_params = {k: v for k, v in [("fields", fields), ("code", code)] if v is not None}
527
419
  response = self._get(url, params=query_params)
528
420
  response.raise_for_status()
529
- if (
530
- response.status_code == 204
531
- or not response.content
532
- or not response.text.strip()
533
- ):
421
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
534
422
  return None
535
423
  try:
536
424
  return response.json()
537
425
  except ValueError:
538
426
  return None
539
427
 
540
- def create_qr_code(
541
- self,
542
- api_version: str,
543
- business_phone_number_id: str,
544
- code: str | None = None,
545
- prefilled_message: str | None = None,
428
+ async def create_qr_code(
429
+ self, api_version: str, business_phone_number_id: str, code: str | None = None, prefilled_message: str | None = None
546
430
  ) -> dict[str, Any]:
547
431
  """
548
432
  Generates a WhatsApp Business QR code for a specific phone number. This function allows setting a prefilled message for user convenience and can optionally include a custom identifier. It returns the details of the newly created QR code upon successful generation.
@@ -568,34 +452,20 @@ class WhatsappBusinessApp(APIApplication):
568
452
  if business_phone_number_id is None:
569
453
  raise ValueError("Missing required parameter 'business-phone-number-id'.")
570
454
  request_body_data = None
571
- request_body_data = {
572
- "code": code,
573
- "prefilled_message": prefilled_message,
574
- }
575
- request_body_data = {
576
- k: v for k, v in request_body_data.items() if v is not None
577
- }
455
+ request_body_data = {"code": code, "prefilled_message": prefilled_message}
456
+ request_body_data = {k: v for k, v in request_body_data.items() if v is not None}
578
457
  url = f"{self.base_url}/{api_version}/{business_phone_number_id}/message_qrdls"
579
458
  query_params = {}
580
- response = self._post(
581
- url,
582
- data=request_body_data,
583
- params=query_params,
584
- content_type="application/json",
585
- )
459
+ response = self._post(url, data=request_body_data, params=query_params, content_type="application/json")
586
460
  response.raise_for_status()
587
- if (
588
- response.status_code == 204
589
- or not response.content
590
- or not response.text.strip()
591
- ):
461
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
592
462
  return None
593
463
  try:
594
464
  return response.json()
595
465
  except ValueError:
596
466
  return None
597
467
 
598
- def get_template_by_id(self, api_version: str) -> dict[str, Any]:
468
+ async def get_template_by_id(self, api_version: str) -> dict[str, Any]:
599
469
  """
600
470
  Retrieves a specific WhatsApp message template by its unique identifier. Unlike `get_template_by_name`, which searches within a business account, this function directly fetches a single template resource. Note: The function signature is missing the required `template_id` parameter to build a valid URL.
601
471
 
@@ -618,18 +488,14 @@ class WhatsappBusinessApp(APIApplication):
618
488
  query_params = {}
619
489
  response = self._get(url, params=query_params)
620
490
  response.raise_for_status()
621
- if (
622
- response.status_code == 204
623
- or not response.content
624
- or not response.text.strip()
625
- ):
491
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
626
492
  return None
627
493
  try:
628
494
  return response.json()
629
495
  except ValueError:
630
496
  return None
631
497
 
632
- def update_template_by_id(
498
+ async def update_template_by_id(
633
499
  self,
634
500
  api_version: str,
635
501
  category: str | None = None,
@@ -660,38 +526,20 @@ class WhatsappBusinessApp(APIApplication):
660
526
  if api_version is None:
661
527
  raise ValueError("Missing required parameter 'api-version'.")
662
528
  request_body_data = None
663
- request_body_data = {
664
- "category": category,
665
- "components": components,
666
- "language": language,
667
- "name": name,
668
- }
669
- request_body_data = {
670
- k: v for k, v in request_body_data.items() if v is not None
671
- }
529
+ request_body_data = {"category": category, "components": components, "language": language, "name": name}
530
+ request_body_data = {k: v for k, v in request_body_data.items() if v is not None}
672
531
  url = f"{self.base_url}/{api_version}/<TEMPLATE_ID>"
673
532
  query_params = {}
674
- response = self._post(
675
- url,
676
- data=request_body_data,
677
- params=query_params,
678
- content_type="application/json",
679
- )
533
+ response = self._post(url, data=request_body_data, params=query_params, content_type="application/json")
680
534
  response.raise_for_status()
681
- if (
682
- response.status_code == 204
683
- or not response.content
684
- or not response.text.strip()
685
- ):
535
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
686
536
  return None
687
537
  try:
688
538
  return response.json()
689
539
  except ValueError:
690
540
  return None
691
541
 
692
- def get_message_templates(
693
- self, api_version: str, waba_id: str, name: str | None = None
694
- ) -> dict[str, Any]:
542
+ async def get_message_templates(self, api_version: str, waba_id: str, name: str | None = None) -> dict[str, Any]:
695
543
  """
696
544
  Retrieves message templates for a specific WhatsApp Business Account (WABA). It can list all templates or, if a name is provided, filter for an exact match. This differs from `get_template_by_id_default_fields`, which fetches a single template by its unique ID.
697
545
 
@@ -718,18 +566,14 @@ class WhatsappBusinessApp(APIApplication):
718
566
  query_params = {k: v for k, v in [("name", name)] if v is not None}
719
567
  response = self._get(url, params=query_params)
720
568
  response.raise_for_status()
721
- if (
722
- response.status_code == 204
723
- or not response.content
724
- or not response.text.strip()
725
- ):
569
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
726
570
  return None
727
571
  try:
728
572
  return response.json()
729
573
  except ValueError:
730
574
  return None
731
575
 
732
- def create_message_template(
576
+ async def create_message_template(
733
577
  self,
734
578
  api_version: str,
735
579
  waba_id: str,
@@ -764,41 +608,21 @@ class WhatsappBusinessApp(APIApplication):
764
608
  if waba_id is None:
765
609
  raise ValueError("Missing required parameter 'waba-id'.")
766
610
  request_body_data = None
767
- request_body_data = {
768
- "category": category,
769
- "components": components,
770
- "language": language,
771
- "name": name,
772
- }
773
- request_body_data = {
774
- k: v for k, v in request_body_data.items() if v is not None
775
- }
611
+ request_body_data = {"category": category, "components": components, "language": language, "name": name}
612
+ request_body_data = {k: v for k, v in request_body_data.items() if v is not None}
776
613
  url = f"{self.base_url}/{api_version}/{waba_id}/message_templates"
777
614
  query_params = {}
778
- response = self._post(
779
- url,
780
- data=request_body_data,
781
- params=query_params,
782
- content_type="application/json",
783
- )
615
+ response = self._post(url, data=request_body_data, params=query_params, content_type="application/json")
784
616
  response.raise_for_status()
785
- if (
786
- response.status_code == 204
787
- or not response.content
788
- or not response.text.strip()
789
- ):
617
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
790
618
  return None
791
619
  try:
792
620
  return response.json()
793
621
  except ValueError:
794
622
  return None
795
623
 
796
- def delete_message_template(
797
- self,
798
- api_version: str,
799
- waba_id: str,
800
- name: str | None = None,
801
- hsm_id: str | None = None,
624
+ async def delete_message_template(
625
+ self, api_version: str, waba_id: str, name: str | None = None, hsm_id: str | None = None
802
626
  ) -> dict[str, Any]:
803
627
  """
804
628
  Deletes a message template from a WhatsApp Business Account. Templates can be targeted for deletion by providing either a template name, which deletes all language versions, or a specific template ID (`hsm_id`).
@@ -824,23 +648,17 @@ class WhatsappBusinessApp(APIApplication):
824
648
  if waba_id is None:
825
649
  raise ValueError("Missing required parameter 'waba-id'.")
826
650
  url = f"{self.base_url}/{api_version}/{waba_id}/message_templates"
827
- query_params = {
828
- k: v for k, v in [("name", name), ("hsm_id", hsm_id)] if v is not None
829
- }
651
+ query_params = {k: v for k, v in [("name", name), ("hsm_id", hsm_id)] if v is not None}
830
652
  response = self._delete(url, params=query_params)
831
653
  response.raise_for_status()
832
- if (
833
- response.status_code == 204
834
- or not response.content
835
- or not response.text.strip()
836
- ):
654
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
837
655
  return None
838
656
  try:
839
657
  return response.json()
840
658
  except ValueError:
841
659
  return None
842
660
 
843
- def get_subscribed_apps(self, api_version: str, waba_id: str) -> dict[str, Any]:
661
+ async def get_subscribed_apps(self, api_version: str, waba_id: str) -> dict[str, Any]:
844
662
  """
845
663
  Retrieves a list of all applications subscribed to receive webhook notifications for a given WhatsApp Business Account (WABA). This function provides a read-only view of current webhook subscriptions, complementing the functions for subscribing and unsubscribing apps.
846
664
 
@@ -866,20 +684,14 @@ class WhatsappBusinessApp(APIApplication):
866
684
  query_params = {}
867
685
  response = self._get(url, params=query_params)
868
686
  response.raise_for_status()
869
- if (
870
- response.status_code == 204
871
- or not response.content
872
- or not response.text.strip()
873
- ):
687
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
874
688
  return None
875
689
  try:
876
690
  return response.json()
877
691
  except ValueError:
878
692
  return None
879
693
 
880
- def subscribe_app_to_webhooks(
881
- self, api_version: str, waba_id: str
882
- ) -> dict[str, Any]:
694
+ async def subscribe_app_to_webhooks(self, api_version: str, waba_id: str) -> dict[str, Any]:
883
695
  """
884
696
  Subscribes an application to a specific WhatsApp Business Account's (WABA) webhooks using its ID. This enables the app to receive real-time event notifications, differentiating it from functions that list or remove subscriptions.
885
697
 
@@ -904,27 +716,16 @@ class WhatsappBusinessApp(APIApplication):
904
716
  request_body_data = None
905
717
  url = f"{self.base_url}/{api_version}/{waba_id}/subscribed_apps"
906
718
  query_params = {}
907
- response = self._post(
908
- url,
909
- data=request_body_data,
910
- params=query_params,
911
- content_type="application/json",
912
- )
719
+ response = self._post(url, data=request_body_data, params=query_params, content_type="application/json")
913
720
  response.raise_for_status()
914
- if (
915
- response.status_code == 204
916
- or not response.content
917
- or not response.text.strip()
918
- ):
721
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
919
722
  return None
920
723
  try:
921
724
  return response.json()
922
725
  except ValueError:
923
726
  return None
924
727
 
925
- def unsubscribe_app_from_waba(
926
- self, api_version: str, waba_id: str
927
- ) -> dict[str, Any]:
728
+ async def unsubscribe_app_from_waba(self, api_version: str, waba_id: str) -> dict[str, Any]:
928
729
  """
929
730
  Removes the webhook subscription for the calling app from a specified WhatsApp Business Account (WABA), stopping it from receiving notifications. This function complements `get_subscribed_apps` and `subscribe_app_to_waba_swebhooks` by handling the deletion of a subscription.
930
731
 
@@ -950,18 +751,14 @@ class WhatsappBusinessApp(APIApplication):
950
751
  query_params = {}
951
752
  response = self._delete(url, params=query_params)
952
753
  response.raise_for_status()
953
- if (
954
- response.status_code == 204
955
- or not response.content
956
- or not response.text.strip()
957
- ):
754
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
958
755
  return None
959
756
  try:
960
757
  return response.json()
961
758
  except ValueError:
962
759
  return None
963
760
 
964
- def get_all_client_wabas(self, api_version: str, business_account_id: str) -> Any:
761
+ async def get_all_client_wabas(self, api_version: str, business_account_id: str) -> Any:
965
762
  """
966
763
  Retrieves all client WhatsApp Business Accounts (WABAs) associated with a specific business account ID. It's used by Solution Partners to list WABAs they manage for other businesses, distinguishing them from accounts they directly own (`get_all_owned_wabas`).
967
764
 
@@ -987,20 +784,14 @@ class WhatsappBusinessApp(APIApplication):
987
784
  query_params = {}
988
785
  response = self._get(url, params=query_params)
989
786
  response.raise_for_status()
990
- if (
991
- response.status_code == 204
992
- or not response.content
993
- or not response.text.strip()
994
- ):
787
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
995
788
  return None
996
789
  try:
997
790
  return response.json()
998
791
  except ValueError:
999
792
  return None
1000
793
 
1001
- def get_all_owned_wabas(
1002
- self, api_version: str, business_account_id: str
1003
- ) -> dict[str, Any]:
794
+ async def get_all_owned_wabas(self, api_version: str, business_account_id: str) -> dict[str, Any]:
1004
795
  """
1005
796
  Retrieves a list of all WhatsApp Business Accounts (WABAs) directly owned by a specified business account. This is distinct from `get_all_shared_wabas`, which fetches WABAs shared with clients, providing specific access to owned assets instead of associated ones.
1006
797
 
@@ -1026,11 +817,7 @@ class WhatsappBusinessApp(APIApplication):
1026
817
  query_params = {}
1027
818
  response = self._get(url, params=query_params)
1028
819
  response.raise_for_status()
1029
- if (
1030
- response.status_code == 204
1031
- or not response.content
1032
- or not response.text.strip()
1033
- ):
820
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
1034
821
  return None
1035
822
  try:
1036
823
  return response.json()