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,17 +1,13 @@
1
1
  from collections.abc import Callable
2
2
  from datetime import datetime
3
3
  from typing import Any
4
-
5
4
  from loguru import logger
6
5
 
7
6
  try:
8
7
  from twilio.rest import Client as TwilioClient
9
8
  except ImportError:
10
9
  TwilioClient = None
11
- logger.error(
12
- "Twilio SDK is not installed. Please install 'twilio' to use TwilioApp."
13
- )
14
-
10
+ logger.error("Twilio SDK is not installed. Please install 'twilio' to use TwilioApp.")
15
11
  from universal_mcp.applications.application import APIApplication
16
12
  from universal_mcp.exceptions import NotAuthorizedError, ToolError
17
13
  from universal_mcp.integrations import Integration
@@ -29,9 +25,7 @@ class TwilioApp(APIApplication):
29
25
  self._account_sid: str | None = None
30
26
  self._auth_token: str | None = None
31
27
  if TwilioClient is None:
32
- logger.warning(
33
- "Twilio SDK is not available. Twilio tools will not function."
34
- )
28
+ logger.warning("Twilio SDK is not available. Twilio tools will not function.")
35
29
 
36
30
  @property
37
31
  def account_sid(self) -> str:
@@ -45,16 +39,9 @@ class TwilioApp(APIApplication):
45
39
  credentials = self.integration.get_credentials()
46
40
  except Exception as e:
47
41
  raise NotAuthorizedError(f"Failed to get Twilio credentials: {e}")
48
-
49
- sid = (
50
- credentials.get("account_sid")
51
- or credentials.get("ACCOUNT_SID")
52
- or credentials.get("TWILIO_ACCOUNT_SID")
53
- )
42
+ sid = credentials.get("account_sid") or credentials.get("ACCOUNT_SID") or credentials.get("TWILIO_ACCOUNT_SID")
54
43
  if not sid:
55
- raise NotAuthorizedError(
56
- "Twilio Account SID is missing. Please set it in the integration."
57
- )
44
+ raise NotAuthorizedError("Twilio Account SID is missing. Please set it in the integration.")
58
45
  self._account_sid = sid
59
46
  return self._account_sid
60
47
 
@@ -70,16 +57,9 @@ class TwilioApp(APIApplication):
70
57
  credentials = self.integration.get_credentials()
71
58
  except Exception as e:
72
59
  raise NotAuthorizedError(f"Failed to get Twilio credentials: {e}")
73
-
74
- token = (
75
- credentials.get("auth_token")
76
- or credentials.get("AUTH_TOKEN")
77
- or credentials.get("TWILIO_AUTH_TOKEN")
78
- )
60
+ token = credentials.get("auth_token") or credentials.get("AUTH_TOKEN") or credentials.get("TWILIO_AUTH_TOKEN")
79
61
  if not token:
80
- raise NotAuthorizedError(
81
- "Twilio Auth Token is missing. Please set it in the integration."
82
- )
62
+ raise NotAuthorizedError("Twilio Auth Token is missing. Please set it in the integration.")
83
63
  self._auth_token = token
84
64
  return self._auth_token
85
65
 
@@ -94,7 +74,7 @@ class TwilioApp(APIApplication):
94
74
  self._twilio_client = TwilioClient(self.account_sid, self.auth_token)
95
75
  return self._twilio_client
96
76
 
97
- def create_message(self, from_: str, to: str, body: str) -> dict[str, Any]:
77
+ async def create_message(self, from_: str, to: str, body: str) -> dict[str, Any]:
98
78
  """
99
79
  Sends a new SMS or MMS message using Twilio.
100
80
 
@@ -114,12 +94,7 @@ class TwilioApp(APIApplication):
114
94
  create, message, sms, mms, send, twilio, api, important
115
95
  """
116
96
  try:
117
- message = self.twilio_client.messages.create(
118
- from_=from_,
119
- to=to,
120
- body=body,
121
- )
122
- # Convert the Twilio MessageInstance to a dict
97
+ message = self.twilio_client.messages.create(from_=from_, to=to, body=body)
123
98
  return {
124
99
  "sid": message.sid,
125
100
  "status": message.status,
@@ -137,7 +112,7 @@ class TwilioApp(APIApplication):
137
112
  raise NotAuthorizedError(f"Twilio authentication failed: {e}")
138
113
  raise ToolError(f"Failed to send message: {e}")
139
114
 
140
- def fetch_message(self, message_sid: str) -> dict[str, Any]:
115
+ async def fetch_message(self, message_sid: str) -> dict[str, Any]:
141
116
  """
142
117
  Fetches the details of a specific message by its SID.
143
118
 
@@ -173,11 +148,8 @@ class TwilioApp(APIApplication):
173
148
  raise NotAuthorizedError(f"Twilio authentication failed: {e}")
174
149
  raise ToolError(f"Failed to fetch message: {e}")
175
150
 
176
- def list_messages(
177
- self,
178
- limit: int = 20,
179
- date_sent_before: datetime | None = None,
180
- date_sent_after: datetime | None = None,
151
+ async def list_messages(
152
+ self, limit: int = 20, date_sent_before: datetime | None = None, date_sent_after: datetime | None = None
181
153
  ) -> list[dict[str, Any]]:
182
154
  """
183
155
  Lists messages from your Twilio account, optionally filtered by date.
@@ -198,14 +170,11 @@ class TwilioApp(APIApplication):
198
170
  list, message, sms, mms, read, twilio, api, important
199
171
  """
200
172
  try:
201
- params = {
202
- "limit": limit,
203
- }
173
+ params = {"limit": limit}
204
174
  if date_sent_before:
205
175
  params["date_sent_before"] = date_sent_before
206
176
  if date_sent_after:
207
177
  params["date_sent_after"] = date_sent_after
208
-
209
178
  messages = self.twilio_client.messages.list(**params)
210
179
  result = []
211
180
  for msg in messages:
@@ -229,7 +198,7 @@ class TwilioApp(APIApplication):
229
198
  raise NotAuthorizedError(f"Twilio authentication failed: {e}")
230
199
  raise ToolError(f"Failed to list messages: {e}")
231
200
 
232
- def delete_message(self, message_sid: str) -> bool:
201
+ async def delete_message(self, message_sid: str) -> bool:
233
202
  """
234
203
  Deletes a specific message from your Twilio account.
235
204
 
@@ -261,9 +230,4 @@ class TwilioApp(APIApplication):
261
230
  Returns:
262
231
  A list of callable tool methods.
263
232
  """
264
- return [
265
- self.create_message,
266
- self.fetch_message,
267
- self.list_messages,
268
- self.delete_message,
269
- ]
233
+ return [self.create_message, self.fetch_message, self.list_messages, self.delete_message]
@@ -7,9 +7,7 @@ class ComplianceApi(APISegmentBase):
7
7
  def __init__(self, main_app_client: Any):
8
8
  super().__init__(main_app_client)
9
9
 
10
- def list_batch_compliance_jobs(
11
- self, type, status=None, compliance_job_fields=None
12
- ) -> dict[str, Any]:
10
+ def list_batch_compliance_jobs(self, type, status=None, compliance_job_fields=None) -> dict[str, Any]:
13
11
  """
14
12
  Retrieves a list of compliance jobs, requiring a job `type` ('tweets' or 'users') and allowing optional filtering by `status`. This function fetches multiple jobs, distinguishing it from `get_batch_compliance_job` which retrieves a single job by its unique ID.
15
13
 
@@ -42,9 +40,7 @@ class ComplianceApi(APISegmentBase):
42
40
  response.raise_for_status()
43
41
  return response.json()
44
42
 
45
- def create_batch_compliance_job(
46
- self, type, name=None, resumable=None
47
- ) -> dict[str, Any]:
43
+ def create_batch_compliance_job(self, type, name=None, resumable=None) -> dict[str, Any]:
48
44
  """
49
45
  Creates a new batch compliance job for a specified type ('tweets' or 'users'). A custom name can be provided, and resumable uploads can be enabled. This initiates the job creation process, differing from functions that list or retrieve existing jobs.
50
46
 
@@ -65,9 +61,7 @@ class ComplianceApi(APISegmentBase):
65
61
  """
66
62
  request_body_data = None
67
63
  request_body_data = {"name": name, "resumable": resumable, "type": type}
68
- request_body_data = {
69
- k: v for k, v in request_body_data.items() if v is not None
70
- }
64
+ request_body_data = {k: v for k, v in request_body_data.items() if v is not None}
71
65
  url = f"{self.main_app_client.base_url}/2/compliance/jobs"
72
66
  query_params = {}
73
67
  response = self._post(
@@ -100,11 +94,7 @@ class ComplianceApi(APISegmentBase):
100
94
  if id is None:
101
95
  raise ValueError("Missing required parameter 'id'.")
102
96
  url = f"{self.main_app_client.base_url}/2/compliance/jobs/{id}"
103
- query_params = {
104
- k: v
105
- for k, v in [("compliance_job.fields", compliance_job_fields)]
106
- if v is not None
107
- }
97
+ query_params = {k: v for k, v in [("compliance_job.fields", compliance_job_fields)] if v is not None}
108
98
  response = self._get(url, params=query_params)
109
99
  response.raise_for_status()
110
100
  return response.json()
@@ -7,9 +7,7 @@ class DmConversationsApi(APISegmentBase):
7
7
  def __init__(self, main_app_client: Any):
8
8
  super().__init__(main_app_client)
9
9
 
10
- def create_dm_conversation(
11
- self, conversation_type=None, message=None, participant_ids=None
12
- ) -> dict[str, Any]:
10
+ def create_dm_conversation(self, conversation_type=None, message=None, participant_ids=None) -> dict[str, Any]:
13
11
  """
14
12
  Creates a new group Direct Message conversation with specified participants and sends an initial message. This function specifically handles the creation of new multi-participant conversations, distinct from other methods in this class that add messages to existing one-to-one or group DMs.
15
13
 
@@ -34,9 +32,7 @@ class DmConversationsApi(APISegmentBase):
34
32
  "message": message,
35
33
  "participant_ids": participant_ids,
36
34
  }
37
- request_body_data = {
38
- k: v for k, v in request_body_data.items() if v is not None
39
- }
35
+ request_body_data = {k: v for k, v in request_body_data.items() if v is not None}
40
36
  url = f"{self.main_app_client.base_url}/2/dm_conversations"
41
37
  query_params = {}
42
38
  response = self._post(
@@ -105,9 +101,7 @@ class DmConversationsApi(APISegmentBase):
105
101
  response.raise_for_status()
106
102
  return response.json()
107
103
 
108
- def send_dm_by_participant_id(
109
- self, participant_id, attachments=None, text=None
110
- ) -> dict[str, Any]:
104
+ def send_dm_by_participant_id(self, participant_id, attachments=None, text=None) -> dict[str, Any]:
111
105
  """
112
106
  Sends a direct message to a user specified by their participant ID. It creates a new one-on-one conversation or appends the message to an existing one. Unlike other functions, this method identifies the conversation using the participant's ID rather than a pre-existing conversation ID.
113
107
 
@@ -130,9 +124,7 @@ class DmConversationsApi(APISegmentBase):
130
124
  raise ValueError("Missing required parameter 'participant_id'.")
131
125
  request_body_data = None
132
126
  request_body_data = {"attachments": attachments, "text": text}
133
- request_body_data = {
134
- k: v for k, v in request_body_data.items() if v is not None
135
- }
127
+ request_body_data = {k: v for k, v in request_body_data.items() if v is not None}
136
128
  url = f"{self.main_app_client.base_url}/2/dm_conversations/with/{participant_id}/messages"
137
129
  query_params = {}
138
130
  response = self._post(
@@ -144,9 +136,7 @@ class DmConversationsApi(APISegmentBase):
144
136
  response.raise_for_status()
145
137
  return response.json()
146
138
 
147
- def add_message_to_dm_conversation(
148
- self, dm_conversation_id, attachments=None, text=None
149
- ) -> dict[str, Any]:
139
+ def add_message_to_dm_conversation(self, dm_conversation_id, attachments=None, text=None) -> dict[str, Any]:
150
140
  """
151
141
  Sends a new message with optional text and attachments to an existing Direct Message conversation. The target conversation is specified by its `dm_conversation_id`, distinguishing it from functions that create new conversations or send one-to-one messages using a participant ID.
152
142
 
@@ -169,9 +159,7 @@ class DmConversationsApi(APISegmentBase):
169
159
  raise ValueError("Missing required parameter 'dm_conversation_id'.")
170
160
  request_body_data = None
171
161
  request_body_data = {"attachments": attachments, "text": text}
172
- request_body_data = {
173
- k: v for k, v in request_body_data.items() if v is not None
174
- }
162
+ request_body_data = {k: v for k, v in request_body_data.items() if v is not None}
175
163
  url = f"{self.main_app_client.base_url}/2/dm_conversations/{dm_conversation_id}/messages"
176
164
  query_params = {}
177
165
  response = self._post(
@@ -7,9 +7,7 @@ class LikesApi(APISegmentBase):
7
7
  def __init__(self, main_app_client: Any):
8
8
  super().__init__(main_app_client)
9
9
 
10
- def get_likes_compliance_stream(
11
- self, backfill_minutes=None, start_time=None, end_time=None
12
- ) -> Any:
10
+ def get_likes_compliance_stream(self, backfill_minutes=None, start_time=None, end_time=None) -> Any:
13
11
  """
14
12
  Streams compliance-related data for 'like' events, such as un-likes, with optional time and backfill filters. This endpoint is for compliance monitoring, differing from the firehose and sample streams which provide real-time like creation events.
15
13
 
@@ -32,9 +32,7 @@ class ListsApi(APISegmentBase):
32
32
  "name": name,
33
33
  "private": private,
34
34
  }
35
- request_body_data = {
36
- k: v for k, v in request_body_data.items() if v is not None
37
- }
35
+ request_body_data = {k: v for k, v in request_body_data.items() if v is not None}
38
36
  url = f"{self.main_app_client.base_url}/2/lists"
39
37
  query_params = {}
40
38
  response = self._post(
@@ -71,9 +69,7 @@ class ListsApi(APISegmentBase):
71
69
  response.raise_for_status()
72
70
  return response.json()
73
71
 
74
- def get_list_by_id(
75
- self, id, list_fields=None, expansions=None, user_fields=None
76
- ) -> dict[str, Any]:
72
+ def get_list_by_id(self, id, list_fields=None, expansions=None, user_fields=None) -> dict[str, Any]:
77
73
  """
78
74
  Retrieves detailed information for a specific list by its ID. This function allows for response customization by specifying which list and user fields to return and supports expansions to include related objects like the owner's user data.
79
75
 
@@ -109,9 +105,7 @@ class ListsApi(APISegmentBase):
109
105
  response.raise_for_status()
110
106
  return response.json()
111
107
 
112
- def update_list(
113
- self, id, description=None, name=None, private=None
114
- ) -> dict[str, Any]:
108
+ def update_list(self, id, description=None, name=None, private=None) -> dict[str, Any]:
115
109
  """
116
110
  Modifies an existing Twitter list identified by its unique ID. This function updates the list's name, description, or privacy status by sending a PUT request to the API and returns the updated list data upon success.
117
111
 
@@ -139,9 +133,7 @@ class ListsApi(APISegmentBase):
139
133
  "name": name,
140
134
  "private": private,
141
135
  }
142
- request_body_data = {
143
- k: v for k, v in request_body_data.items() if v is not None
144
- }
136
+ request_body_data = {k: v for k, v in request_body_data.items() if v is not None}
145
137
  url = f"{self.main_app_client.base_url}/2/lists/{id}"
146
138
  query_params = {}
147
139
  response = self._put(
@@ -271,9 +263,7 @@ class ListsApi(APISegmentBase):
271
263
  raise ValueError("Missing required parameter 'id'.")
272
264
  request_body_data = None
273
265
  request_body_data = {"user_id": user_id}
274
- request_body_data = {
275
- k: v for k, v in request_body_data.items() if v is not None
276
- }
266
+ request_body_data = {k: v for k, v in request_body_data.items() if v is not None}
277
267
  url = f"{self.main_app_client.base_url}/2/lists/{id}/members"
278
268
  query_params = {}
279
269
  response = self._post(
@@ -28,9 +28,7 @@ class TrendsApi(APISegmentBase):
28
28
  if woeid is None:
29
29
  raise ValueError("Missing required parameter 'woeid'.")
30
30
  url = f"{self.main_app_client.base_url}/2/trends/by/woeid/{woeid}"
31
- query_params = {
32
- k: v for k, v in [("trend.fields", trend_fields)] if v is not None
33
- }
31
+ query_params = {k: v for k, v in [("trend.fields", trend_fields)] if v is not None}
34
32
  response = self._get(url, params=query_params)
35
33
  response.raise_for_status()
36
34
  return response.json()
@@ -111,9 +111,7 @@ class TweetsApi(APISegmentBase):
111
111
  "reply_settings": reply_settings,
112
112
  "text": text,
113
113
  }
114
- request_body_data = {
115
- k: v for k, v in request_body_data.items() if v is not None
116
- }
114
+ request_body_data = {k: v for k, v in request_body_data.items() if v is not None}
117
115
  url = f"{self.main_app_client.base_url}/2/tweets"
118
116
  query_params = {}
119
117
  response = self._post(
@@ -125,9 +123,7 @@ class TweetsApi(APISegmentBase):
125
123
  response.raise_for_status()
126
124
  return response.json()
127
125
 
128
- def get_tweets_compliance_stream(
129
- self, partition, backfill_minutes=None, start_time=None, end_time=None
130
- ) -> Any:
126
+ def get_tweets_compliance_stream(self, partition, backfill_minutes=None, start_time=None, end_time=None) -> Any:
131
127
  """
132
128
  Streams real-time compliance events for tweets, such as deletions and user updates, from a specified partition. Unlike other stream functions that return tweet content, this provides metadata about content and user status changes, supporting optional time-based filtering and backfilling.
133
129
 
@@ -569,9 +565,7 @@ class TweetsApi(APISegmentBase):
569
565
  response.raise_for_status()
570
566
  return response.json()
571
567
 
572
- def stream_labeled_tweets(
573
- self, backfill_minutes=None, start_time=None, end_time=None
574
- ) -> Any:
568
+ def stream_labeled_tweets(self, backfill_minutes=None, start_time=None, end_time=None) -> Any:
575
569
  """
576
570
  Streams real-time Tweet objects labeled for compliance reasons, such as withheld content. Unlike `get_tweets_compliance_stream`, which provides events, this returns the actual tweets. Supports filtering by a time window and backfilling missed data upon reconnection.
577
571
 
@@ -917,9 +911,7 @@ class TweetsApi(APISegmentBase):
917
911
  response.raise_for_status()
918
912
  return response.json()
919
913
 
920
- def get_filtered_stream_rules(
921
- self, ids=None, max_results=None, pagination_token=None
922
- ) -> dict[str, Any]:
914
+ def get_filtered_stream_rules(self, ids=None, max_results=None, pagination_token=None) -> dict[str, Any]:
923
915
  """
924
916
  Retrieves the active filtering rules for a Twitter API v2 filtered stream. It can fetch all rules or a subset specified by rule IDs, with support for pagination to manage large rule sets, complementing the `add_or_delete_rules` and `search_stream` functions.
925
917
 
@@ -952,9 +944,7 @@ class TweetsApi(APISegmentBase):
952
944
  response.raise_for_status()
953
945
  return response.json()
954
946
 
955
- def update_stream_rules(
956
- self, dry_run=None, delete_all=None, add=None, delete=None
957
- ) -> dict[str, Any]:
947
+ def update_stream_rules(self, dry_run=None, delete_all=None, add=None, delete=None) -> dict[str, Any]:
958
948
  """
959
949
  Adds or removes filtering rules for a tweet stream. Supports a dry-run mode to validate rule syntax without application and an option to delete all existing rules. This function directly modifies the active rule set used by the `search_stream` function.
960
950
 
@@ -976,15 +966,9 @@ class TweetsApi(APISegmentBase):
976
966
  """
977
967
  request_body_data = None
978
968
  request_body_data = {"add": add, "delete": delete}
979
- request_body_data = {
980
- k: v for k, v in request_body_data.items() if v is not None
981
- }
969
+ request_body_data = {k: v for k, v in request_body_data.items() if v is not None}
982
970
  url = f"{self.main_app_client.base_url}/2/tweets/search/stream/rules"
983
- query_params = {
984
- k: v
985
- for k, v in [("dry_run", dry_run), ("delete_all", delete_all)]
986
- if v is not None
987
- }
971
+ query_params = {k: v for k, v in [("dry_run", dry_run), ("delete_all", delete_all)] if v is not None}
988
972
  response = self._post(
989
973
  url,
990
974
  data=request_body_data,
@@ -1012,11 +996,7 @@ class TweetsApi(APISegmentBase):
1012
996
  General
1013
997
  """
1014
998
  url = f"{self.main_app_client.base_url}/2/tweets/search/stream/rules/counts"
1015
- query_params = {
1016
- k: v
1017
- for k, v in [("rules_count.fields", rules_count_fields)]
1018
- if v is not None
1019
- }
999
+ query_params = {k: v for k, v in [("rules_count.fields", rules_count_fields)] if v is not None}
1020
1000
  response = self._get(url, params=query_params)
1021
1001
  response.raise_for_status()
1022
1002
  return response.json()
@@ -1332,9 +1312,7 @@ class TweetsApi(APISegmentBase):
1332
1312
  raise ValueError("Missing required parameter 'tweet_id'.")
1333
1313
  request_body_data = None
1334
1314
  request_body_data = {"hidden": hidden}
1335
- request_body_data = {
1336
- k: v for k, v in request_body_data.items() if v is not None
1337
- }
1315
+ request_body_data = {k: v for k, v in request_body_data.items() if v is not None}
1338
1316
  url = f"{self.main_app_client.base_url}/2/tweets/{tweet_id}/hidden"
1339
1317
  query_params = {}
1340
1318
  response = self._put(
@@ -26,11 +26,7 @@ class UsageApi(APISegmentBase):
26
26
  Usage
27
27
  """
28
28
  url = f"{self.main_app_client.base_url}/2/usage/tweets"
29
- query_params = {
30
- k: v
31
- for k, v in [("days", days), ("usage.fields", usage_fields)]
32
- if v is not None
33
- }
29
+ query_params = {k: v for k, v in [("days", days), ("usage.fields", usage_fields)] if v is not None}
34
30
  response = self._get(url, params=query_params)
35
31
  response.raise_for_status()
36
32
  return response.json()
@@ -7,9 +7,7 @@ class UsersApi(APISegmentBase):
7
7
  def __init__(self, main_app_client: Any):
8
8
  super().__init__(main_app_client)
9
9
 
10
- def get_users_by_ids(
11
- self, ids, user_fields=None, expansions=None, tweet_fields=None
12
- ) -> dict[str, Any]:
10
+ def get_users_by_ids(self, ids, user_fields=None, expansions=None, tweet_fields=None) -> dict[str, Any]:
13
11
  """
14
12
  Retrieves detailed information for multiple users in a single API request, specified by a list of their unique IDs. Unlike `find_user_by_id`, which fetches a single user, this function performs a bulk lookup and allows for response customization with optional fields and expansions.
15
13
 
@@ -44,9 +42,7 @@ class UsersApi(APISegmentBase):
44
42
  response.raise_for_status()
45
43
  return response.json()
46
44
 
47
- def get_users_by_usernames(
48
- self, usernames, user_fields=None, expansions=None, tweet_fields=None
49
- ) -> dict[str, Any]:
45
+ def get_users_by_usernames(self, usernames, user_fields=None, expansions=None, tweet_fields=None) -> dict[str, Any]:
50
46
  """
51
47
  Fetches public data for a batch of users specified by their usernames. This function supports retrieving multiple users in a single request, unlike `find_user_by_username`. It allows for data customization through optional fields and expansions.
52
48
 
@@ -81,9 +77,7 @@ class UsersApi(APISegmentBase):
81
77
  response.raise_for_status()
82
78
  return response.json()
83
79
 
84
- def find_user_by_username(
85
- self, username, user_fields=None, expansions=None, tweet_fields=None
86
- ) -> dict[str, Any]:
80
+ def find_user_by_username(self, username, user_fields=None, expansions=None, tweet_fields=None) -> dict[str, Any]:
87
81
  """
88
82
  Retrieves detailed information for a single user specified by their username, with options to include additional user, tweet, and expansion fields. This differs from `find_users_by_username`, which fetches data for multiple users in a single request.
89
83
 
@@ -119,9 +113,7 @@ class UsersApi(APISegmentBase):
119
113
  response.raise_for_status()
120
114
  return response.json()
121
115
 
122
- def get_users_compliance_stream(
123
- self, partition, backfill_minutes=None, start_time=None, end_time=None
124
- ) -> Any:
116
+ def get_users_compliance_stream(self, partition, backfill_minutes=None, start_time=None, end_time=None) -> Any:
125
117
  """
126
118
  Streams real-time user compliance events, such as account deletions or suspensions, from a specified data partition. Allows for backfilling missed data after a disconnection and filtering the event stream by a specific time range for targeted data retrieval.
127
119
 
@@ -156,9 +148,7 @@ class UsersApi(APISegmentBase):
156
148
  response.raise_for_status()
157
149
  return response.json()
158
150
 
159
- def get_authenticated_user(
160
- self, user_fields=None, expansions=None, tweet_fields=None
161
- ) -> dict[str, Any]:
151
+ def get_authenticated_user(self, user_fields=None, expansions=None, tweet_fields=None) -> dict[str, Any]:
162
152
  """
163
153
  Retrieves detailed information about the authenticated user making the request. Optional parameters allow for customizing the returned user and tweet data fields and including expanded objects. This differs from other 'find' functions as it requires no ID or username.
164
154
 
@@ -238,9 +228,7 @@ class UsersApi(APISegmentBase):
238
228
  response.raise_for_status()
239
229
  return response.json()
240
230
 
241
- def find_user_by_id(
242
- self, id, user_fields=None, expansions=None, tweet_fields=None
243
- ) -> dict[str, Any]:
231
+ def find_user_by_id(self, id, user_fields=None, expansions=None, tweet_fields=None) -> dict[str, Any]:
244
232
  """
245
233
  Retrieves detailed information for a single user specified by their unique ID. This function allows for response customization using optional fields and expansions. It differs from `find_users_by_id`, which fetches data for multiple users in a single request.
246
234
 
@@ -403,9 +391,7 @@ class UsersApi(APISegmentBase):
403
391
  raise ValueError("Missing required parameter 'id'.")
404
392
  request_body_data = None
405
393
  request_body_data = {"tweet_id": tweet_id}
406
- request_body_data = {
407
- k: v for k, v in request_body_data.items() if v is not None
408
- }
394
+ request_body_data = {k: v for k, v in request_body_data.items() if v is not None}
409
395
  url = f"{self.main_app_client.base_url}/2/users/{id}/bookmarks"
410
396
  query_params = {}
411
397
  response = self._post(
@@ -515,9 +501,7 @@ class UsersApi(APISegmentBase):
515
501
  raise ValueError("Missing required parameter 'id'.")
516
502
  request_body_data = None
517
503
  request_body_data = {"list_id": list_id}
518
- request_body_data = {
519
- k: v for k, v in request_body_data.items() if v is not None
520
- }
504
+ request_body_data = {k: v for k, v in request_body_data.items() if v is not None}
521
505
  url = f"{self.main_app_client.base_url}/2/users/{id}/followed_lists"
522
506
  query_params = {}
523
507
  response = self._post(
@@ -675,9 +659,7 @@ class UsersApi(APISegmentBase):
675
659
  raise ValueError("Missing required parameter 'id'.")
676
660
  request_body_data = None
677
661
  request_body_data = {"target_user_id": target_user_id}
678
- request_body_data = {
679
- k: v for k, v in request_body_data.items() if v is not None
680
- }
662
+ request_body_data = {k: v for k, v in request_body_data.items() if v is not None}
681
663
  url = f"{self.main_app_client.base_url}/2/users/{id}/following"
682
664
  query_params = {}
683
665
  response = self._post(
@@ -768,9 +750,7 @@ class UsersApi(APISegmentBase):
768
750
  raise ValueError("Missing required parameter 'id'.")
769
751
  request_body_data = None
770
752
  request_body_data = {"tweet_id": tweet_id}
771
- request_body_data = {
772
- k: v for k, v in request_body_data.items() if v is not None
773
- }
753
+ request_body_data = {k: v for k, v in request_body_data.items() if v is not None}
774
754
  url = f"{self.main_app_client.base_url}/2/users/{id}/likes"
775
755
  query_params = {}
776
756
  response = self._post(
@@ -997,9 +977,7 @@ class UsersApi(APISegmentBase):
997
977
  raise ValueError("Missing required parameter 'id'.")
998
978
  request_body_data = None
999
979
  request_body_data = {"target_user_id": target_user_id}
1000
- request_body_data = {
1001
- k: v for k, v in request_body_data.items() if v is not None
1002
- }
980
+ request_body_data = {k: v for k, v in request_body_data.items() if v is not None}
1003
981
  url = f"{self.main_app_client.base_url}/2/users/{id}/muting"
1004
982
  query_params = {}
1005
983
  response = self._post(
@@ -1059,9 +1037,7 @@ class UsersApi(APISegmentBase):
1059
1037
  response.raise_for_status()
1060
1038
  return response.json()
1061
1039
 
1062
- def get_user_pinned_lists(
1063
- self, id, list_fields=None, expansions=None, user_fields=None
1064
- ) -> dict[str, Any]:
1040
+ def get_user_pinned_lists(self, id, list_fields=None, expansions=None, user_fields=None) -> dict[str, Any]:
1065
1041
  """
1066
1042
  Retrieves the collection of lists pinned by a specific user, identified by their ID. Optional parameters allow for customizing the returned list and user data fields, and including expansions. This is distinct from fetching lists a user follows or owns.
1067
1043
 
@@ -1119,9 +1095,7 @@ class UsersApi(APISegmentBase):
1119
1095
  raise ValueError("Missing required parameter 'id'.")
1120
1096
  request_body_data = None
1121
1097
  request_body_data = {"list_id": list_id}
1122
- request_body_data = {
1123
- k: v for k, v in request_body_data.items() if v is not None
1124
- }
1098
+ request_body_data = {k: v for k, v in request_body_data.items() if v is not None}
1125
1099
  url = f"{self.main_app_client.base_url}/2/users/{id}/pinned_lists"
1126
1100
  query_params = {}
1127
1101
  response = self._post(
@@ -1183,9 +1157,7 @@ class UsersApi(APISegmentBase):
1183
1157
  raise ValueError("Missing required parameter 'id'.")
1184
1158
  request_body_data = None
1185
1159
  request_body_data = {"tweet_id": tweet_id}
1186
- request_body_data = {
1187
- k: v for k, v in request_body_data.items() if v is not None
1188
- }
1160
+ request_body_data = {k: v for k, v in request_body_data.items() if v is not None}
1189
1161
  url = f"{self.main_app_client.base_url}/2/users/{id}/retweets"
1190
1162
  query_params = {}
1191
1163
  response = self._post(