marqetive-lib 0.1.12__py3-none-any.whl → 0.1.14__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.
- marqetive/platforms/twitter/client.py +21 -18
- marqetive/utils/oauth.py +41 -6
- {marqetive_lib-0.1.12.dist-info → marqetive_lib-0.1.14.dist-info}/METADATA +1 -1
- {marqetive_lib-0.1.12.dist-info → marqetive_lib-0.1.14.dist-info}/RECORD +5 -5
- {marqetive_lib-0.1.12.dist-info → marqetive_lib-0.1.14.dist-info}/WHEEL +0 -0
|
@@ -207,14 +207,6 @@ class TwitterClient(SocialMediaPlatform):
|
|
|
207
207
|
platform=self.platform_name,
|
|
208
208
|
)
|
|
209
209
|
|
|
210
|
-
# Validate tweet length (280 characters)
|
|
211
|
-
if request.content and len(request.content) > 280:
|
|
212
|
-
raise ValidationError(
|
|
213
|
-
f"Tweet exceeds 280 characters ({len(request.content)} characters)",
|
|
214
|
-
platform=self.platform_name,
|
|
215
|
-
field="content",
|
|
216
|
-
)
|
|
217
|
-
|
|
218
210
|
try:
|
|
219
211
|
media_ids = []
|
|
220
212
|
|
|
@@ -234,11 +226,17 @@ class TwitterClient(SocialMediaPlatform):
|
|
|
234
226
|
if media_ids:
|
|
235
227
|
tweet_params["media_ids"] = media_ids
|
|
236
228
|
|
|
237
|
-
response = self._tweepy_client.create_tweet(**tweet_params)
|
|
229
|
+
response = self._tweepy_client.create_tweet(**tweet_params, user_auth=False)
|
|
238
230
|
tweet_id = response.data["id"] # type: ignore[index]
|
|
239
231
|
|
|
240
|
-
#
|
|
241
|
-
return
|
|
232
|
+
# Return minimal Post object without fetching details
|
|
233
|
+
return Post(
|
|
234
|
+
post_id=tweet_id,
|
|
235
|
+
platform=self.platform_name,
|
|
236
|
+
content=request.content or "",
|
|
237
|
+
status=PostStatus.PUBLISHED,
|
|
238
|
+
created_at=datetime.now(),
|
|
239
|
+
)
|
|
242
240
|
|
|
243
241
|
except tweepy.TweepyException as e:
|
|
244
242
|
if "429" in str(e):
|
|
@@ -278,6 +276,7 @@ class TwitterClient(SocialMediaPlatform):
|
|
|
278
276
|
],
|
|
279
277
|
expansions=["attachments.media_keys"],
|
|
280
278
|
media_fields=["url", "type", "width", "height"],
|
|
279
|
+
user_auth=False,
|
|
281
280
|
)
|
|
282
281
|
|
|
283
282
|
if not response.data: # type: ignore[attr-defined]
|
|
@@ -339,7 +338,7 @@ class TwitterClient(SocialMediaPlatform):
|
|
|
339
338
|
raise RuntimeError("Client must be used as async context manager")
|
|
340
339
|
|
|
341
340
|
try:
|
|
342
|
-
self._tweepy_client.delete_tweet(post_id)
|
|
341
|
+
self._tweepy_client.delete_tweet(post_id, user_auth=False)
|
|
343
342
|
return True
|
|
344
343
|
|
|
345
344
|
except tweepy.errors.NotFound as e: # type: ignore[attr-defined]
|
|
@@ -432,18 +431,22 @@ class TwitterClient(SocialMediaPlatform):
|
|
|
432
431
|
response = self._tweepy_client.create_tweet(
|
|
433
432
|
text=content,
|
|
434
433
|
in_reply_to_tweet_id=post_id,
|
|
434
|
+
user_auth=False,
|
|
435
435
|
)
|
|
436
436
|
|
|
437
437
|
reply_id = response.data["id"] # type: ignore[index]
|
|
438
438
|
|
|
439
|
-
#
|
|
440
|
-
|
|
441
|
-
reply_id,
|
|
442
|
-
|
|
439
|
+
# Return minimal Comment object without fetching details
|
|
440
|
+
return Comment(
|
|
441
|
+
comment_id=reply_id,
|
|
442
|
+
post_id=post_id,
|
|
443
|
+
platform=self.platform_name,
|
|
444
|
+
content=content,
|
|
445
|
+
author_id="",
|
|
446
|
+
created_at=datetime.now(),
|
|
447
|
+
status=CommentStatus.VISIBLE,
|
|
443
448
|
)
|
|
444
449
|
|
|
445
|
-
return self._parse_reply(reply_response.data, post_id) # type: ignore[attr-defined]
|
|
446
|
-
|
|
447
450
|
except tweepy.TweepyException as e:
|
|
448
451
|
raise PlatformError(
|
|
449
452
|
f"Failed to create reply: {e}",
|
marqetive/utils/oauth.py
CHANGED
|
@@ -120,6 +120,9 @@ async def refresh_twitter_token(
|
|
|
120
120
|
) -> AuthCredentials:
|
|
121
121
|
"""Refresh Twitter OAuth2 access token.
|
|
122
122
|
|
|
123
|
+
Twitter requires HTTP Basic Authentication with client credentials
|
|
124
|
+
in the Authorization header, not in the request body.
|
|
125
|
+
|
|
123
126
|
Args:
|
|
124
127
|
credentials: Current credentials with refresh token.
|
|
125
128
|
client_id: Twitter OAuth client ID.
|
|
@@ -144,6 +147,8 @@ async def refresh_twitter_token(
|
|
|
144
147
|
... os.getenv("TWITTER_CLIENT_SECRET")
|
|
145
148
|
... )
|
|
146
149
|
"""
|
|
150
|
+
import base64
|
|
151
|
+
|
|
147
152
|
if not credentials.refresh_token:
|
|
148
153
|
raise PlatformAuthError(
|
|
149
154
|
"No refresh token available",
|
|
@@ -152,12 +157,42 @@ async def refresh_twitter_token(
|
|
|
152
157
|
|
|
153
158
|
token_url = "https://api.x.com/2/oauth2/token"
|
|
154
159
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
160
|
+
# Twitter requires Basic Auth header for confidential clients
|
|
161
|
+
basic_auth = base64.b64encode(f"{client_id}:{client_secret}".encode()).decode()
|
|
162
|
+
|
|
163
|
+
params = {
|
|
164
|
+
"grant_type": "refresh_token",
|
|
165
|
+
"refresh_token": credentials.refresh_token,
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
try:
|
|
169
|
+
async with httpx.AsyncClient() as client:
|
|
170
|
+
response = await client.post(
|
|
171
|
+
token_url,
|
|
172
|
+
data=params,
|
|
173
|
+
headers={
|
|
174
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
175
|
+
"Authorization": f"Basic {basic_auth}",
|
|
176
|
+
},
|
|
177
|
+
timeout=30.0,
|
|
178
|
+
)
|
|
179
|
+
response.raise_for_status()
|
|
180
|
+
token_data = response.json()
|
|
181
|
+
|
|
182
|
+
except httpx.HTTPStatusError as e:
|
|
183
|
+
logger.error(f"HTTP error refreshing Twitter token: {e.response.status_code}")
|
|
184
|
+
raise PlatformAuthError(
|
|
185
|
+
f"Failed to refresh token: {_sanitize_response_text(e.response.text)}",
|
|
186
|
+
platform="twitter",
|
|
187
|
+
status_code=e.response.status_code,
|
|
188
|
+
) from e
|
|
189
|
+
|
|
190
|
+
except httpx.HTTPError as e:
|
|
191
|
+
logger.error(f"Network error refreshing Twitter token: {e}")
|
|
192
|
+
raise PlatformAuthError(
|
|
193
|
+
f"Network error refreshing token: {e}",
|
|
194
|
+
platform="twitter",
|
|
195
|
+
) from e
|
|
161
196
|
|
|
162
197
|
# Update credentials
|
|
163
198
|
credentials.access_token = token_data["access_token"]
|
|
@@ -22,7 +22,7 @@ marqetive/platforms/tiktok/exceptions.py,sha256=vxwyAKujMGZJh0LetG1QsLF95QfUs_kR
|
|
|
22
22
|
marqetive/platforms/tiktok/media.py,sha256=aa47EDRA7woKGqKZkl_5XWu7kcRp2nT93Ol2skEQJpY,28592
|
|
23
23
|
marqetive/platforms/tiktok/models.py,sha256=WWdjuFqhTIR8SnHkz-8UaNc5Mm2PrGomwQ3W7pJcQFg,2962
|
|
24
24
|
marqetive/platforms/twitter/__init__.py,sha256=dvcgVT-v-JOtjSz-OUvxGrn_43OI6w_ep42Wx_nHTSM,217
|
|
25
|
-
marqetive/platforms/twitter/client.py,sha256=
|
|
25
|
+
marqetive/platforms/twitter/client.py,sha256=ATjNOLV3LLVAPo7An_O1G0Sd0NX4t2hljn_EF7foUaY,23345
|
|
26
26
|
marqetive/platforms/twitter/exceptions.py,sha256=eZ-dJKOXH_-bAMg29zWKbEqMFud29piEJ5IWfC9wFts,8926
|
|
27
27
|
marqetive/platforms/twitter/media.py,sha256=KpPxnLCas8NhnsEvaXSJZ7To4wW4FY0YqQvUkJIIr7g,28010
|
|
28
28
|
marqetive/platforms/twitter/models.py,sha256=yPQlx40SlNmz7YGasXUqdx7rEDEgrQ64aYovlPKo6oc,2126
|
|
@@ -31,9 +31,9 @@ marqetive/utils/__init__.py,sha256=bSrNajbxYBSKQayrPviLz8JeGjplnyK8y_NGDtgb7yQ,9
|
|
|
31
31
|
marqetive/utils/file_handlers.py,sha256=4TP5kmWofNTSZmlS683CM1UYP83WvRd_NubMbqtXv-g,12568
|
|
32
32
|
marqetive/utils/helpers.py,sha256=8-ljhL47SremKcQO2GF8DIHOPODEv1rSioVNuSPCbec,2634
|
|
33
33
|
marqetive/utils/media.py,sha256=O1rISYdaP3CuuPxso7kqvxWXNfe2jjioNkaBc4cpwkY,14668
|
|
34
|
-
marqetive/utils/oauth.py,sha256=
|
|
34
|
+
marqetive/utils/oauth.py,sha256=gi5OS_gTit_pG8pyC3I934ayavi_TVnhHwZTwbeoGe4,14364
|
|
35
35
|
marqetive/utils/retry.py,sha256=lAniJLMNWp9XsHrvU0XBNifpNEjfde4MGfd5hlFTPfA,7636
|
|
36
36
|
marqetive/utils/token_validator.py,sha256=dNvDeHs2Du5UyMMH2ZOW6ydR7OwOEKA4c9e-rG0f9-0,6698
|
|
37
|
-
marqetive_lib-0.1.
|
|
38
|
-
marqetive_lib-0.1.
|
|
39
|
-
marqetive_lib-0.1.
|
|
37
|
+
marqetive_lib-0.1.14.dist-info/METADATA,sha256=GOW1Yf5xAkT3prFFfWRu-4oZEzM1yrPPJxHnOHyBr7o,7876
|
|
38
|
+
marqetive_lib-0.1.14.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
39
|
+
marqetive_lib-0.1.14.dist-info/RECORD,,
|
|
File without changes
|