universal-mcp-applications 0.1.17__py3-none-any.whl → 0.1.33__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.

Potentially problematic release.


This version of universal-mcp-applications might be problematic. Click here for more details.

Files changed (143) hide show
  1. universal_mcp/applications/BEST_PRACTICES.md +166 -0
  2. universal_mcp/applications/ahrefs/README.md +3 -3
  3. universal_mcp/applications/airtable/README.md +3 -3
  4. universal_mcp/applications/airtable/app.py +0 -1
  5. universal_mcp/applications/apollo/app.py +0 -1
  6. universal_mcp/applications/asana/README.md +3 -3
  7. universal_mcp/applications/aws_s3/README.md +29 -0
  8. universal_mcp/applications/aws_s3/app.py +40 -39
  9. universal_mcp/applications/bill/README.md +249 -0
  10. universal_mcp/applications/browser_use/README.md +1 -0
  11. universal_mcp/applications/browser_use/__init__.py +0 -0
  12. universal_mcp/applications/browser_use/app.py +71 -0
  13. universal_mcp/applications/calendly/README.md +45 -45
  14. universal_mcp/applications/calendly/app.py +125 -125
  15. universal_mcp/applications/canva/README.md +35 -35
  16. universal_mcp/applications/canva/app.py +95 -99
  17. universal_mcp/applications/clickup/README.md +4 -4
  18. universal_mcp/applications/confluence/app.py +0 -1
  19. universal_mcp/applications/contentful/README.md +1 -2
  20. universal_mcp/applications/contentful/app.py +4 -5
  21. universal_mcp/applications/crustdata/README.md +3 -3
  22. universal_mcp/applications/domain_checker/README.md +2 -2
  23. universal_mcp/applications/domain_checker/app.py +11 -15
  24. universal_mcp/applications/e2b/README.md +4 -4
  25. universal_mcp/applications/e2b/app.py +4 -4
  26. universal_mcp/applications/elevenlabs/README.md +3 -77
  27. universal_mcp/applications/elevenlabs/app.py +18 -15
  28. universal_mcp/applications/exa/README.md +7 -7
  29. universal_mcp/applications/exa/app.py +17 -17
  30. universal_mcp/applications/falai/README.md +13 -12
  31. universal_mcp/applications/falai/app.py +34 -35
  32. universal_mcp/applications/figma/README.md +3 -3
  33. universal_mcp/applications/file_system/README.md +13 -0
  34. universal_mcp/applications/file_system/app.py +9 -9
  35. universal_mcp/applications/firecrawl/README.md +9 -9
  36. universal_mcp/applications/firecrawl/app.py +46 -46
  37. universal_mcp/applications/fireflies/README.md +14 -14
  38. universal_mcp/applications/fireflies/app.py +164 -57
  39. universal_mcp/applications/fpl/README.md +12 -12
  40. universal_mcp/applications/fpl/app.py +54 -55
  41. universal_mcp/applications/ghost_content/app.py +0 -1
  42. universal_mcp/applications/github/README.md +10 -10
  43. universal_mcp/applications/github/app.py +50 -52
  44. universal_mcp/applications/google_calendar/README.md +10 -10
  45. universal_mcp/applications/google_calendar/app.py +50 -49
  46. universal_mcp/applications/google_docs/README.md +14 -14
  47. universal_mcp/applications/google_docs/app.py +307 -233
  48. universal_mcp/applications/google_drive/README.md +54 -57
  49. universal_mcp/applications/google_drive/app.py +270 -261
  50. universal_mcp/applications/google_gemini/README.md +3 -14
  51. universal_mcp/applications/google_gemini/app.py +15 -18
  52. universal_mcp/applications/google_mail/README.md +20 -20
  53. universal_mcp/applications/google_mail/app.py +110 -109
  54. universal_mcp/applications/google_searchconsole/README.md +10 -10
  55. universal_mcp/applications/google_searchconsole/app.py +37 -37
  56. universal_mcp/applications/google_sheet/README.md +25 -25
  57. universal_mcp/applications/google_sheet/app.py +270 -266
  58. universal_mcp/applications/hashnode/README.md +6 -3
  59. universal_mcp/applications/hashnode/app.py +174 -25
  60. universal_mcp/applications/http_tools/README.md +5 -5
  61. universal_mcp/applications/http_tools/app.py +10 -11
  62. universal_mcp/applications/hubspot/api_segments/__init__.py +0 -0
  63. universal_mcp/applications/hubspot/api_segments/api_segment_base.py +54 -0
  64. universal_mcp/applications/hubspot/api_segments/crm_api.py +7337 -0
  65. universal_mcp/applications/hubspot/api_segments/marketing_api.py +1467 -0
  66. universal_mcp/applications/hubspot/app.py +2 -15
  67. universal_mcp/applications/jira/app.py +0 -1
  68. universal_mcp/applications/klaviyo/README.md +0 -36
  69. universal_mcp/applications/linkedin/README.md +18 -4
  70. universal_mcp/applications/linkedin/app.py +763 -162
  71. universal_mcp/applications/mailchimp/README.md +3 -3
  72. universal_mcp/applications/markitdown/app.py +10 -5
  73. universal_mcp/applications/ms_teams/README.md +31 -31
  74. universal_mcp/applications/ms_teams/app.py +151 -151
  75. universal_mcp/applications/neon/README.md +3 -3
  76. universal_mcp/applications/onedrive/README.md +24 -0
  77. universal_mcp/applications/onedrive/__init__.py +1 -0
  78. universal_mcp/applications/onedrive/app.py +338 -0
  79. universal_mcp/applications/openai/README.md +18 -17
  80. universal_mcp/applications/openai/app.py +40 -39
  81. universal_mcp/applications/outlook/README.md +9 -9
  82. universal_mcp/applications/outlook/app.py +307 -225
  83. universal_mcp/applications/perplexity/README.md +4 -4
  84. universal_mcp/applications/perplexity/app.py +4 -4
  85. universal_mcp/applications/posthog/README.md +128 -127
  86. universal_mcp/applications/reddit/README.md +21 -124
  87. universal_mcp/applications/reddit/app.py +51 -68
  88. universal_mcp/applications/resend/README.md +29 -29
  89. universal_mcp/applications/resend/app.py +116 -117
  90. universal_mcp/applications/rocketlane/app.py +0 -1
  91. universal_mcp/applications/scraper/README.md +7 -4
  92. universal_mcp/applications/scraper/__init__.py +1 -1
  93. universal_mcp/applications/scraper/app.py +341 -103
  94. universal_mcp/applications/semrush/README.md +3 -0
  95. universal_mcp/applications/serpapi/README.md +3 -3
  96. universal_mcp/applications/serpapi/app.py +14 -14
  97. universal_mcp/applications/sharepoint/README.md +19 -0
  98. universal_mcp/applications/sharepoint/app.py +285 -173
  99. universal_mcp/applications/shopify/app.py +0 -1
  100. universal_mcp/applications/shortcut/README.md +3 -3
  101. universal_mcp/applications/slack/README.md +23 -0
  102. universal_mcp/applications/slack/app.py +79 -48
  103. universal_mcp/applications/spotify/README.md +3 -3
  104. universal_mcp/applications/supabase/README.md +3 -3
  105. universal_mcp/applications/tavily/README.md +4 -4
  106. universal_mcp/applications/tavily/app.py +4 -4
  107. universal_mcp/applications/twilio/README.md +15 -0
  108. universal_mcp/applications/twitter/README.md +92 -89
  109. universal_mcp/applications/twitter/api_segments/compliance_api.py +13 -15
  110. universal_mcp/applications/twitter/api_segments/dm_conversations_api.py +20 -20
  111. universal_mcp/applications/twitter/api_segments/dm_events_api.py +12 -12
  112. universal_mcp/applications/twitter/api_segments/likes_api.py +12 -12
  113. universal_mcp/applications/twitter/api_segments/lists_api.py +37 -39
  114. universal_mcp/applications/twitter/api_segments/spaces_api.py +24 -24
  115. universal_mcp/applications/twitter/api_segments/trends_api.py +4 -4
  116. universal_mcp/applications/twitter/api_segments/tweets_api.py +105 -105
  117. universal_mcp/applications/twitter/api_segments/usage_api.py +4 -4
  118. universal_mcp/applications/twitter/api_segments/users_api.py +136 -136
  119. universal_mcp/applications/twitter/app.py +15 -11
  120. universal_mcp/applications/whatsapp/README.md +12 -12
  121. universal_mcp/applications/whatsapp/app.py +66 -67
  122. universal_mcp/applications/whatsapp/audio.py +39 -35
  123. universal_mcp/applications/whatsapp/whatsapp.py +176 -154
  124. universal_mcp/applications/whatsapp_business/README.md +23 -23
  125. universal_mcp/applications/whatsapp_business/app.py +92 -92
  126. universal_mcp/applications/yahoo_finance/README.md +17 -0
  127. universal_mcp/applications/yahoo_finance/__init__.py +1 -0
  128. universal_mcp/applications/yahoo_finance/app.py +300 -0
  129. universal_mcp/applications/youtube/README.md +46 -46
  130. universal_mcp/applications/youtube/app.py +208 -195
  131. universal_mcp/applications/zenquotes/README.md +1 -1
  132. universal_mcp/applications/zenquotes/__init__.py +2 -0
  133. universal_mcp/applications/zenquotes/app.py +5 -5
  134. {universal_mcp_applications-0.1.17.dist-info → universal_mcp_applications-0.1.33.dist-info}/METADATA +5 -90
  135. {universal_mcp_applications-0.1.17.dist-info → universal_mcp_applications-0.1.33.dist-info}/RECORD +137 -128
  136. universal_mcp/applications/replicate/README.md +0 -18
  137. universal_mcp/applications/replicate/__init__.py +0 -1
  138. universal_mcp/applications/replicate/app.py +0 -493
  139. universal_mcp/applications/unipile/README.md +0 -28
  140. universal_mcp/applications/unipile/__init__.py +0 -1
  141. universal_mcp/applications/unipile/app.py +0 -827
  142. {universal_mcp_applications-0.1.17.dist-info → universal_mcp_applications-0.1.33.dist-info}/WHEEL +0 -0
  143. {universal_mcp_applications-0.1.17.dist-info → universal_mcp_applications-0.1.33.dist-info}/licenses/LICENSE +0 -0
@@ -1,15 +1,17 @@
1
- import requests
2
1
  import json
3
- from datetime import datetime
4
- from dataclasses import dataclass
5
- from typing import Optional, List, Tuple
6
2
  import os.path
7
- from . import audio
3
+ from dataclasses import dataclass
4
+ from datetime import datetime
5
+
6
+ import requests
8
7
  from dotenv import load_dotenv
9
8
 
9
+ from . import audio
10
+
10
11
  load_dotenv()
11
12
 
12
- WHATSAPP_API_BASE_URL = os.getenv('WHATSAPP_API_BASE_URL', "http://134.209.144.43:8080")
13
+ WHATSAPP_API_BASE_URL = os.getenv("WHATSAPP_API_BASE_URL", "http://134.209.144.43:8080")
14
+
13
15
 
14
16
  @dataclass
15
17
  class Message:
@@ -19,45 +21,51 @@ class Message:
19
21
  is_from_me: bool
20
22
  chat_jid: str
21
23
  id: str
22
- chat_name: Optional[str] = None
23
- media_type: Optional[str] = None
24
+ chat_name: str | None = None
25
+ media_type: str | None = None
26
+
24
27
 
25
28
  @dataclass
26
29
  class Chat:
27
30
  jid: str
28
- name: Optional[str]
29
- last_message_time: Optional[datetime]
30
- last_message: Optional[str] = None
31
- last_sender: Optional[str] = None
32
- last_is_from_me: Optional[bool] = None
31
+ name: str | None
32
+ last_message_time: datetime | None
33
+ last_message: str | None = None
34
+ last_sender: str | None = None
35
+ last_is_from_me: bool | None = None
33
36
 
34
37
  @property
35
38
  def is_group(self) -> bool:
36
39
  """Determine if chat is a group based on JID pattern."""
37
40
  return self.jid.endswith("@g.us")
38
41
 
42
+
39
43
  @dataclass
40
44
  class Contact:
41
45
  phone_number: str
42
- name: Optional[str]
46
+ name: str | None
43
47
  jid: str
44
48
 
49
+
45
50
  @dataclass
46
51
  class MessageContext:
47
52
  message: Message
48
- before: List[Message]
49
- after: List[Message]
53
+ before: list[Message]
54
+ after: list[Message]
55
+
50
56
 
51
- def _make_api_request(endpoint: str, method: str = "GET", data: dict = None, user_id: str = "default_user") -> dict:
57
+ def _make_api_request(
58
+ endpoint: str, method: str = "GET", data: dict = None, user_id: str = "default_user"
59
+ ) -> dict:
52
60
  """Make HTTP request to WhatsApp Bridge API."""
53
61
  url = f"{WHATSAPP_API_BASE_URL}/api/{endpoint}"
54
-
62
+
55
63
  # Add user_id to query parameters for GET requests
56
64
  if method.upper() == "GET" and data:
57
65
  data["user_id"] = user_id
58
66
  elif method.upper() == "GET":
59
67
  data = {"user_id": user_id}
60
-
68
+
61
69
  try:
62
70
  if method.upper() == "GET":
63
71
  response = requests.get(url, params=data, timeout=30)
@@ -65,68 +73,80 @@ def _make_api_request(endpoint: str, method: str = "GET", data: dict = None, use
65
73
  response = requests.post(url, json=data, timeout=30)
66
74
  else:
67
75
  raise ValueError(f"Unsupported HTTP method: {method}")
68
-
76
+
69
77
  if response.status_code == 200:
70
78
  return response.json()
71
79
  else:
72
80
  return {"error": f"HTTP {response.status_code}: {response.text}"}
73
-
81
+
74
82
  except requests.RequestException as e:
75
83
  return {"error": f"Request failed: {str(e)}"}
76
84
  except json.JSONDecodeError:
77
85
  return {"error": f"Invalid JSON response: {response.text}"}
78
86
 
87
+
79
88
  def get_sender_name(sender_jid: str, user_id: str = "default_user") -> str:
80
89
  """Get sender name via API call."""
81
- result = _make_api_request("sender_name", data={"sender_jid": sender_jid}, user_id=user_id)
82
-
90
+ result = _make_api_request(
91
+ "sender_name", data={"sender_jid": sender_jid}, user_id=user_id
92
+ )
93
+
83
94
  if "error" in result:
84
95
  return sender_jid
85
-
96
+
86
97
  return result.get("name", sender_jid)
87
98
 
88
- def format_message(message: Message, show_chat_info: bool = True, user_id: str = "default_user") -> str:
99
+
100
+ def format_message(
101
+ message: Message, show_chat_info: bool = True, user_id: str = "default_user"
102
+ ) -> str:
89
103
  """Print a single message with consistent formatting."""
90
104
  output = ""
91
-
105
+
92
106
  if show_chat_info and message.chat_name:
93
107
  output += f"[{message.timestamp:%Y-%m-%d %H:%M:%S}] Chat: {message.chat_name} "
94
108
  else:
95
109
  output += f"[{message.timestamp:%Y-%m-%d %H:%M:%S}] "
96
-
110
+
97
111
  content_prefix = ""
98
- if hasattr(message, 'media_type') and message.media_type:
112
+ if hasattr(message, "media_type") and message.media_type:
99
113
  content_prefix = f"[{message.media_type} - Message ID: {message.id} - Chat JID: {message.chat_jid}] "
100
-
114
+
101
115
  try:
102
- sender_name = get_sender_name(message.sender, user_id) if not message.is_from_me else "Me"
116
+ sender_name = (
117
+ get_sender_name(message.sender, user_id) if not message.is_from_me else "Me"
118
+ )
103
119
  output += f"From: {sender_name}: {content_prefix}{message.content}\n"
104
- except Exception as e:
105
- print(f"Error formatting message: {e}")
120
+ except Exception:
121
+ pass
106
122
  return output
107
123
 
108
- def format_messages_list(messages: List[Message], show_chat_info: bool = True, user_id: str = "default_user") -> str:
124
+
125
+ def format_messages_list(
126
+ messages: list[Message], show_chat_info: bool = True, user_id: str = "default_user"
127
+ ) -> str:
109
128
  output = ""
110
129
  if not messages:
111
130
  output += "No messages to display."
112
131
  return output
113
-
132
+
114
133
  for message in messages:
115
134
  output += format_message(message, show_chat_info, user_id)
116
135
  return output
117
136
 
137
+
118
138
  def list_messages(
119
- after: Optional[str] = None,
120
- before: Optional[str] = None,
121
- sender_phone_number: Optional[str] = None,
122
- chat_jid: Optional[str] = None,
123
- query: Optional[str] = None,
139
+ after: str | None = None,
140
+ before: str | None = None,
141
+ sender_phone_number: str | None = None,
142
+ chat_jid: str | None = None,
143
+ query: str | None = None,
124
144
  limit: int = 20,
125
145
  page: int = 0,
126
146
  include_context: bool = True,
127
147
  context_before: int = 1,
128
148
  context_after: int = 1,
129
- user_id: str = "default_user"
149
+ user_id: str = "default_user",
130
150
  ) -> str:
131
151
  """Get messages matching the specified criteria with optional context via API."""
132
152
  params = {
@@ -139,260 +159,262 @@ def list_messages(
139
159
  "page": page,
140
160
  "include_context": include_context,
141
161
  "context_before": context_before,
142
- "context_after": context_after
162
+ "context_after": context_after,
143
163
  }
144
-
164
+
145
165
  # Remove None values
146
166
  params = {k: v for k, v in params.items() if v is not None}
147
-
167
+
148
168
  result = _make_api_request("messages", data=params, user_id=user_id)
149
-
169
+
150
170
  if "error" in result:
151
171
  return f"Error retrieving messages: {result['error']}"
152
-
172
+
153
173
  return result.get("messages", "No messages found")
154
174
 
175
+
155
176
  def get_message_context(
156
- message_id: str,
157
- before: int = 5,
158
- after: int = 5,
159
- user_id: str = "default_user"
177
+ message_id: str, before: int = 5, after: int = 5, user_id: str = "default_user"
160
178
  ) -> MessageContext:
161
179
  """Get context around a specific message via API."""
162
- params = {
163
- "message_id": message_id,
164
- "before": before,
165
- "after": after
166
- }
167
-
180
+ params = {"message_id": message_id, "before": before, "after": after}
181
+
168
182
  result = _make_api_request("message_context", data=params, user_id=user_id)
169
-
183
+
170
184
  if "error" in result:
171
185
  raise ValueError(f"Error getting message context: {result['error']}")
172
-
186
+
173
187
  # Parse the response into MessageContext object
174
188
  # This would need to be implemented based on the API response structure
175
189
  # For now, returning a simple error message
176
190
  raise NotImplementedError("Message context API not yet implemented in bridge")
177
191
 
192
+
178
193
  def list_chats(
179
- query: Optional[str] = None,
194
+ query: str | None = None,
180
195
  limit: int = 20,
181
196
  page: int = 0,
182
197
  include_last_message: bool = True,
183
198
  sort_by: str = "last_active",
184
- user_id: str = "default_user"
185
- ) -> List[Chat]:
199
+ user_id: str = "default_user",
200
+ ) -> list[Chat]:
186
201
  """Get chats matching the specified criteria via API."""
187
202
  params = {
188
203
  "query": query,
189
204
  "limit": limit,
190
205
  "page": page,
191
206
  "include_last_message": include_last_message,
192
- "sort_by": sort_by
207
+ "sort_by": sort_by,
193
208
  }
194
-
209
+
195
210
  # Remove None values
196
211
  params = {k: v for k, v in params.items() if v is not None}
197
-
212
+
198
213
  result = _make_api_request("chats", data=params, user_id=user_id)
199
-
214
+
200
215
  if "error" in result:
201
- print(f"Error retrieving chats: {result['error']}")
202
216
  return []
203
-
217
+
204
218
  chats_data = result.get("chats", [])
205
219
  chats = []
206
-
220
+
207
221
  for chat_data in chats_data:
208
222
  chat = Chat(
209
223
  jid=chat_data["jid"],
210
224
  name=chat_data.get("name"),
211
- last_message_time=datetime.fromisoformat(chat_data["last_message_time"]) if chat_data.get("last_message_time") else None,
225
+ last_message_time=datetime.fromisoformat(chat_data["last_message_time"])
226
+ if chat_data.get("last_message_time")
227
+ else None,
212
228
  last_message=chat_data.get("last_message"),
213
229
  last_sender=chat_data.get("last_sender"),
214
- last_is_from_me=chat_data.get("last_is_from_me")
230
+ last_is_from_me=chat_data.get("last_is_from_me"),
215
231
  )
216
232
  chats.append(chat)
217
-
233
+
218
234
  return chats
219
235
 
220
- def search_contacts(query: str, user_id: str = "default_user") -> List[Contact]:
236
+
237
+ def search_contacts(query: str, user_id: str = "default_user") -> list[Contact]:
221
238
  """Search contacts by name or phone number via API."""
222
239
  result = _make_api_request("contacts", data={"query": query}, user_id=user_id)
223
-
240
+
224
241
  if "error" in result:
225
- print(f"Error searching contacts: {result['error']}")
226
242
  return []
227
-
243
+
228
244
  contacts_data = result.get("contacts", [])
229
245
  contacts = []
230
-
246
+
231
247
  for contact_data in contacts_data:
232
248
  contact = Contact(
233
249
  phone_number=contact_data["phone_number"],
234
250
  name=contact_data.get("name"),
235
- jid=contact_data["jid"]
251
+ jid=contact_data["jid"],
236
252
  )
237
253
  contacts.append(contact)
238
-
254
+
239
255
  return contacts
240
256
 
241
- def get_contact_chats(jid: str, limit: int = 20, page: int = 0, user_id: str = "default_user") -> List[Chat]:
257
+
258
+ def get_contact_chats(
259
+ jid: str, limit: int = 20, page: int = 0, user_id: str = "default_user"
260
+ ) -> list[Chat]:
242
261
  """Get all chats involving the contact via API."""
243
- params = {
244
- "jid": jid,
245
- "limit": limit,
246
- "page": page
247
- }
248
-
262
+ params = {"jid": jid, "limit": limit, "page": page}
263
+
249
264
  result = _make_api_request("contact_chats", data=params, user_id=user_id)
250
-
265
+
251
266
  if "error" in result:
252
- print(f"Error getting contact chats: {result['error']}")
253
267
  return []
254
-
268
+
255
269
  chats_data = result.get("chats", [])
256
270
  chats = []
257
-
271
+
258
272
  for chat_data in chats_data:
259
273
  chat = Chat(
260
274
  jid=chat_data["jid"],
261
275
  name=chat_data.get("name"),
262
- last_message_time=datetime.fromisoformat(chat_data["last_message_time"]) if chat_data.get("last_message_time") else None,
276
+ last_message_time=datetime.fromisoformat(chat_data["last_message_time"])
277
+ if chat_data.get("last_message_time")
278
+ else None,
263
279
  last_message=chat_data.get("last_message"),
264
280
  last_sender=chat_data.get("last_sender"),
265
- last_is_from_me=chat_data.get("last_is_from_me")
281
+ last_is_from_me=chat_data.get("last_is_from_me"),
266
282
  )
267
283
  chats.append(chat)
268
-
284
+
269
285
  return chats
270
286
 
287
+
271
288
  def get_last_interaction(jid: str, user_id: str = "default_user") -> str:
272
289
  """Get most recent message involving the contact via API."""
273
290
  result = _make_api_request("last_interaction", data={"jid": jid}, user_id=user_id)
274
-
291
+
275
292
  if "error" in result:
276
293
  return f"Error getting last interaction: {result['error']}"
277
-
294
+
278
295
  return result.get("message", "No interaction found")
279
296
 
280
- def get_chat(chat_jid: str, include_last_message: bool = True, user_id: str = "default_user") -> Optional[Chat]:
297
+
298
+ def get_chat(
299
+ chat_jid: str, include_last_message: bool = True, user_id: str = "default_user"
300
+ ) -> Chat | None:
281
301
  """Get chat metadata by JID via API."""
282
- params = {
283
- "chat_jid": chat_jid,
284
- "include_last_message": include_last_message
285
- }
286
-
302
+ params = {"chat_jid": chat_jid, "include_last_message": include_last_message}
303
+
287
304
  result = _make_api_request("chat", data=params, user_id=user_id)
288
-
305
+
289
306
  if "error" in result:
290
- print(f"Error getting chat: {result['error']}")
291
307
  return None
292
-
308
+
293
309
  chat_data = result.get("chat")
294
310
  if not chat_data:
295
311
  return None
296
-
312
+
297
313
  return Chat(
298
314
  jid=chat_data["jid"],
299
315
  name=chat_data.get("name"),
300
- last_message_time=datetime.fromisoformat(chat_data["last_message_time"]) if chat_data.get("last_message_time") else None,
316
+ last_message_time=datetime.fromisoformat(chat_data["last_message_time"])
317
+ if chat_data.get("last_message_time")
318
+ else None,
301
319
  last_message=chat_data.get("last_message"),
302
320
  last_sender=chat_data.get("last_sender"),
303
- last_is_from_me=chat_data.get("last_is_from_me")
321
+ last_is_from_me=chat_data.get("last_is_from_me"),
304
322
  )
305
323
 
306
- def get_direct_chat_by_contact(sender_phone_number: str, user_id: str = "default_user") -> Optional[Chat]:
324
+
325
+ def get_direct_chat_by_contact(
326
+ sender_phone_number: str, user_id: str = "default_user"
327
+ ) -> Chat | None:
307
328
  """Get chat metadata by sender phone number via API."""
308
- result = _make_api_request("direct_chat", data={"sender_phone_number": sender_phone_number}, user_id=user_id)
309
-
329
+ result = _make_api_request(
330
+ "direct_chat",
331
+ data={"sender_phone_number": sender_phone_number},
332
+ user_id=user_id,
333
+ )
334
+
310
335
  if "error" in result:
311
- print(f"Error getting direct chat: {result['error']}")
312
336
  return None
313
-
337
+
314
338
  chat_data = result.get("chat")
315
339
  if not chat_data:
316
340
  return None
317
-
341
+
318
342
  return Chat(
319
343
  jid=chat_data["jid"],
320
344
  name=chat_data.get("name"),
321
- last_message_time=datetime.fromisoformat(chat_data["last_message_time"]) if chat_data.get("last_message_time") else None,
345
+ last_message_time=datetime.fromisoformat(chat_data["last_message_time"])
346
+ if chat_data.get("last_message_time")
347
+ else None,
322
348
  last_message=chat_data.get("last_message"),
323
349
  last_sender=chat_data.get("last_sender"),
324
- last_is_from_me=chat_data.get("last_is_from_me")
350
+ last_is_from_me=chat_data.get("last_is_from_me"),
325
351
  )
326
352
 
327
- def send_message(recipient: str, message: str, user_id: str = "default_user") -> Tuple[bool, str]:
353
+
354
+ def send_message(
355
+ recipient: str, message: str, user_id: str = "default_user"
356
+ ) -> tuple[bool, str]:
328
357
  """Send message via API."""
329
- payload = {
330
- "user_id": user_id,
331
- "recipient": recipient,
332
- "message": message
333
- }
334
-
358
+ payload = {"user_id": user_id, "recipient": recipient, "message": message}
359
+
335
360
  result = _make_api_request("send", method="POST", data=payload, user_id=user_id)
336
-
361
+
337
362
  if "error" in result:
338
363
  return False, result["error"]
339
-
364
+
340
365
  return result.get("success", False), result.get("message", "Unknown response")
341
366
 
342
- def send_file(recipient: str, media_path: str, user_id: str = "default_user") -> Tuple[bool, str]:
367
+
368
+ def send_file(
369
+ recipient: str, media_path: str, user_id: str = "default_user"
370
+ ) -> tuple[bool, str]:
343
371
  """Send file via API."""
344
- payload = {
345
- "user_id": user_id,
346
- "recipient": recipient,
347
- "media_path": media_path
348
- }
349
-
372
+ payload = {"user_id": user_id, "recipient": recipient, "media_path": media_path}
373
+
350
374
  result = _make_api_request("send", method="POST", data=payload, user_id=user_id)
351
-
375
+
352
376
  if "error" in result:
353
377
  return False, result["error"]
354
-
378
+
355
379
  return result.get("success", False), result.get("message", "Unknown response")
356
380
 
357
- def send_audio_message(recipient: str, media_path: str, user_id: str = "default_user") -> Tuple[bool, str]:
381
+
382
+ def send_audio_message(
383
+ recipient: str, media_path: str, user_id: str = "default_user"
384
+ ) -> tuple[bool, str]:
358
385
  """Send audio message via API."""
359
386
  if not media_path.endswith(".ogg"):
360
387
  try:
361
388
  media_path = audio.convert_to_opus_ogg_temp(media_path)
362
389
  except Exception as e:
363
- return False, f"Error converting file to opus ogg. You likely need to install ffmpeg: {str(e)}"
364
-
365
- payload = {
366
- "user_id": user_id,
367
- "recipient": recipient,
368
- "media_path": media_path
369
- }
370
-
390
+ return (
391
+ False,
392
+ f"Error converting file to opus ogg. You likely need to install ffmpeg: {str(e)}",
393
+ )
394
+
395
+ payload = {"user_id": user_id, "recipient": recipient, "media_path": media_path}
396
+
371
397
  result = _make_api_request("send", method="POST", data=payload, user_id=user_id)
372
-
398
+
373
399
  if "error" in result:
374
400
  return False, result["error"]
375
-
401
+
376
402
  return result.get("success", False), result.get("message", "Unknown response")
377
403
 
378
- def download_media(message_id: str, chat_jid: str, user_id: str = "default_user") -> Optional[str]:
404
+
405
+ def download_media(
406
+ message_id: str, chat_jid: str, user_id: str = "default_user"
407
+ ) -> str | None:
379
408
  """Download media from a message via API."""
380
- payload = {
381
- "user_id": user_id,
382
- "message_id": message_id,
383
- "chat_jid": chat_jid
384
- }
385
-
409
+ payload = {"user_id": user_id, "message_id": message_id, "chat_jid": chat_jid}
410
+
386
411
  result = _make_api_request("download", method="POST", data=payload, user_id=user_id)
387
-
412
+
388
413
  if "error" in result:
389
- print(f"Download failed: {result['error']}")
390
414
  return None
391
-
415
+
392
416
  if result.get("success", False):
393
417
  path = result.get("path")
394
- print(f"Media downloaded successfully: {path}")
395
418
  return path
396
419
  else:
397
- print(f"Download failed: {result.get('message', 'Unknown error')}")
398
420
  return None
@@ -9,26 +9,26 @@ This is automatically generated from OpenAPI schema for the WhatsappBusinessApp
9
9
 
10
10
  | Tool | Description |
11
11
  |------|-------------|
12
- | `get_analytics` | Retrieves details of a specified WhatsApp Business Account (WABA) with customizable fields using the GET method. |
13
- | `get_credit_lines` | Retrieves the extended credit lines available for a specified business account using its ID. |
14
- | `get_business_account` | Retrieves information about a business account using the specified API version and business account ID, optionally filtering the response fields via a query parameter. |
15
- | `get_commerce_settings` | Retrieves the commerce settings configured for a specific WhatsApp Business phone number. |
16
- | `set_or_update_commerce_settings` | Updates WhatsApp Business commerce settings (cart availability and catalog visibility) for a specific business phone number. |
17
- | `upload_file` | Uploads a file using the specified API version and application ID, with optional query parameters for file length and type, and returns a successful status message upon completion. |
18
- | `resume_session` | Initiates a session using the provided SESSION_ID and file offset specified in the header, supporting further session-related operations via the POST method at the "/{api-version}/<SESSION_ID>" endpoint. |
19
- | `get_business_phone_number` | Retrieves details for a specific business phone number ID using query parameters to specify returned fields. |
20
- | `get_all_business_phone_numbers` | Retrieves a list of phone numbers associated with a specific WhatsApp Business Account (WABA), allowing for filtering and customization of the response fields. |
21
- | `get_qr_code` | Retrieves a message linked to a specific QR code for a business phone number using the GET method via the API. |
22
- | `delete_qr_code` | Deletes a specific WhatsApp Business QR code using the provided QR code ID and returns a success message if the operation is completed successfully. |
23
- | `get_all_qr_codes_default_fields` | Retrieves a list of message QR code deep links associated with a business phone number, filtered by specified fields and QR code identifiers. |
24
- | `create_qr_code` | Creates a WhatsApp Business QR code with a predefined message and returns the generated code details. |
25
- | `get_template_by_id_default_fields` | Retrieves a template using the specified template ID from the API version path. |
26
- | `edit_template` | Creates or processes a resource using the specified template ID based on the API version and returns a successful status upon completion. |
27
- | `get_template_by_name_default_fields` | Retrieves a list of WhatsApp message templates associated with a specific WhatsApp Business Account using the "GET" method, allowing filtering by template name. |
28
- | `create_message_template` | Creates a new WhatsApp message template for a business account, allowing businesses to send standardized messages to customers. |
29
- | `delete_template_by_name` | Deletes WhatsApp message templates by name (all languages) or specific ID using query parameters and returns a success status. |
30
- | `get_subscribed_apps` | Retrieves a list of apps subscribed to webhooks for a WhatsApp Business Account using the GET method. |
31
- | `subscribe_app_to_waba_swebhooks` | Subscribes an app to webhooks for a WhatsApp Business Account (WABA) using the POST method at the `/subscribed_apps` endpoint, allowing the app to receive updates and notifications from the WABA. |
32
- | `unsubscribe_apps_by_waba_id` | Unsubscribes an app from webhook notifications for a WhatsApp Business Account. |
33
- | `get_all_shared_wabas` | Retrieves information about WhatsApp Business accounts associated with a business client, using the specified business account ID and API version. |
34
- | `get_all_owned_wabas` | Retrieves a list of WhatsApp Business Accounts owned by or shared with the specified business account using a GET request to the given endpoint. |
12
+ | `get_whatsapp_business_account` | 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. |
13
+ | `get_business_account_credit_lines` | 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. |
14
+ | `get_business_account` | 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. |
15
+ | `get_commerce_settings` | 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. |
16
+ | `update_commerce_settings` | 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. |
17
+ | `create_upload_session` | 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`. |
18
+ | `upload_file_to_session` | 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. |
19
+ | `get_business_phone_number` | 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. |
20
+ | `list_waba_phone_numbers` | 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. |
21
+ | `get_qr_code_by_id` | 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. |
22
+ | `delete_qr_code_by_id` | 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. |
23
+ | `list_qr_codes` | 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. |
24
+ | `create_qr_code` | 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. |
25
+ | `get_template_by_id` | 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. |
26
+ | `update_template_by_id` | Updates an existing WhatsApp message template, identified by its ID within the request URL. This function modifies the template's category, components, language, and name by submitting new data via a POST request, returning the API response upon successful completion. |
27
+ | `get_message_templates` | 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. |
28
+ | `create_message_template` | Creates a new message template for a specified WhatsApp Business Account (WABA). This function sends a POST request with the template's name, language, category, and structural components, enabling the creation of standardized, reusable messages. |
29
+ | `delete_message_template` | 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`). |
30
+ | `get_subscribed_apps` | 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. |
31
+ | `subscribe_app_to_webhooks` | 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. |
32
+ | `unsubscribe_app_from_waba` | 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. |
33
+ | `get_all_client_wabas` | 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`). |
34
+ | `get_all_owned_wabas` | 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. |