marqetive-lib 0.1.6__py3-none-any.whl → 0.1.7__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.
@@ -0,0 +1,82 @@
1
+ """TikTok-specific models for post creation.
2
+
3
+ This module defines TikTok-specific data models for creating video posts,
4
+ including privacy settings and content toggles.
5
+ """
6
+
7
+ from enum import StrEnum
8
+
9
+ from pydantic import BaseModel, Field
10
+
11
+
12
+ class PrivacyLevel(StrEnum):
13
+ """Privacy level options for TikTok posts.
14
+
15
+ Attributes:
16
+ PUBLIC: Visible to everyone
17
+ FRIENDS: Visible to mutual followers/friends only
18
+ PRIVATE: Visible only to the author (for unaudited apps)
19
+ """
20
+
21
+ PUBLIC = "PUBLIC_TO_EVERYONE"
22
+ FRIENDS = "MUTUAL_FOLLOW_FRIENDS"
23
+ PRIVATE = "SELF_ONLY"
24
+
25
+
26
+ class TikTokPostRequest(BaseModel):
27
+ """TikTok-specific post creation request.
28
+
29
+ TikTok only supports video posts. Videos must be between 3 seconds
30
+ and 10 minutes, and under 4GB in size.
31
+
32
+ Attributes:
33
+ title: Video title/caption (max 2200 characters)
34
+ video_url: URL to video file (required)
35
+ video_id: Pre-uploaded video ID
36
+ privacy_level: Privacy setting (PUBLIC, FRIENDS, PRIVATE)
37
+ disable_comment: Disable comments on the video
38
+ disable_duet: Disable duet feature
39
+ disable_stitch: Disable stitch feature
40
+ video_cover_timestamp_ms: Timestamp in ms for auto-generated cover
41
+ brand_content_toggle: Mark as branded/sponsored content
42
+ brand_organic_toggle: Mark as organic branded content
43
+ schedule_time: Unix timestamp to schedule post (10 mins to 10 days ahead)
44
+
45
+ Example:
46
+ >>> # Public video post
47
+ >>> request = TikTokPostRequest(
48
+ ... title="Check out this dance!",
49
+ ... video_url="https://example.com/dance.mp4",
50
+ ... privacy_level=PrivacyLevel.PUBLIC
51
+ ... )
52
+
53
+ >>> # Private video with features disabled
54
+ >>> request = TikTokPostRequest(
55
+ ... title="Personal video",
56
+ ... video_url="https://example.com/video.mp4",
57
+ ... privacy_level=PrivacyLevel.PRIVATE,
58
+ ... disable_comment=True,
59
+ ... disable_duet=True,
60
+ ... disable_stitch=True
61
+ ... )
62
+
63
+ >>> # Branded content
64
+ >>> request = TikTokPostRequest(
65
+ ... title="Sponsored review",
66
+ ... video_url="https://example.com/review.mp4",
67
+ ... privacy_level=PrivacyLevel.PUBLIC,
68
+ ... brand_content_toggle=True
69
+ ... )
70
+ """
71
+
72
+ title: str | None = None
73
+ video_url: str | None = None
74
+ video_id: str | None = None
75
+ privacy_level: PrivacyLevel = PrivacyLevel.PRIVATE
76
+ disable_comment: bool = False
77
+ disable_duet: bool = False
78
+ disable_stitch: bool = False
79
+ video_cover_timestamp_ms: int | None = None
80
+ brand_content_toggle: bool = False
81
+ brand_organic_toggle: bool = False
82
+ schedule_time: int | None = Field(default=None, description="Unix timestamp")
@@ -1,5 +1,6 @@
1
1
  """Twitter/X platform integration."""
2
2
 
3
3
  from marqetive.platforms.twitter.client import TwitterClient
4
+ from marqetive.platforms.twitter.models import TwitterPostRequest
4
5
 
5
- __all__ = ["TwitterClient"]
6
+ __all__ = ["TwitterClient", "TwitterPostRequest"]
@@ -527,6 +527,92 @@ class TwitterClient(SocialMediaPlatform):
527
527
  media_type=media_type,
528
528
  ) from e
529
529
 
530
+ # ==================== Thread Methods ====================
531
+
532
+ async def create_thread(
533
+ self,
534
+ posts: list[PostCreateRequest],
535
+ ) -> list[Post]:
536
+ """Create a Twitter thread (multiple linked tweets).
537
+
538
+ Each tweet in the list can have its own content, media, polls, and alt texts.
539
+ Tweets are posted sequentially, with each tweet replying to the previous one.
540
+
541
+ Args:
542
+ posts: List of PostCreateRequest objects to create as a thread.
543
+ First tweet is the head of the thread.
544
+ Use TwitterPostRequest for Twitter-specific features.
545
+
546
+ Returns:
547
+ List of Post objects for each tweet in the thread.
548
+
549
+ Raises:
550
+ ValidationError: If posts list is empty.
551
+ PlatformAuthError: If not authenticated.
552
+ MediaUploadError: If media upload fails.
553
+ RuntimeError: If client not used as context manager.
554
+
555
+ Example:
556
+ >>> from marqetive.platforms.twitter import TwitterPostRequest
557
+ >>> tweets = [
558
+ ... TwitterPostRequest(content="Thread start! 1/3"),
559
+ ... TwitterPostRequest(content="Middle 2/3", media_urls=["..."]),
560
+ ... TwitterPostRequest(content="End 3/3", poll_options=["Yes", "No"]),
561
+ ... ]
562
+ >>> async with TwitterClient(credentials) as client:
563
+ ... thread_posts = await client.create_thread(tweets)
564
+ ... for post in thread_posts:
565
+ ... print(f"Tweet {post.post_id}: {post.content}")
566
+ """
567
+ from marqetive.core.models import ProgressStatus
568
+ from marqetive.platforms.twitter.models import TwitterPostRequest
569
+
570
+ if not posts:
571
+ raise ValidationError(
572
+ "At least one tweet is required for thread creation",
573
+ platform=self.platform_name,
574
+ )
575
+
576
+ created_posts: list[Post] = []
577
+ reply_to_id: str | None = None
578
+
579
+ for idx, post_request in enumerate(posts):
580
+ # Convert to TwitterPostRequest if needed and set reply chain
581
+ if isinstance(post_request, TwitterPostRequest):
582
+ if reply_to_id is not None:
583
+ post_request = post_request.model_copy(
584
+ update={"reply_to_post_id": reply_to_id}
585
+ )
586
+ # TwitterPostRequest works with create_post via duck typing
587
+ final_request = post_request
588
+ else:
589
+ # Create TwitterPostRequest from generic PostCreateRequest
590
+ request_data: dict[str, Any] = {
591
+ "content": post_request.content,
592
+ "media_urls": post_request.media_urls,
593
+ "media_ids": post_request.media_ids,
594
+ }
595
+ if reply_to_id is not None:
596
+ request_data["reply_to_post_id"] = reply_to_id
597
+ final_request = TwitterPostRequest(**request_data)
598
+
599
+ # TwitterPostRequest has compatible interface with PostCreateRequest
600
+ created_post = await self.create_post(final_request) # type: ignore[arg-type]
601
+ created_posts.append(created_post)
602
+ reply_to_id = created_post.post_id
603
+
604
+ # Emit progress
605
+ await self._emit_progress(
606
+ operation="create_thread",
607
+ status=ProgressStatus.PROCESSING,
608
+ progress=idx + 1,
609
+ total=len(posts),
610
+ message=f"Tweet {idx + 1}/{len(posts)} created",
611
+ entity_id=created_post.post_id,
612
+ )
613
+
614
+ return created_posts
615
+
530
616
  # ==================== Helper Methods ====================
531
617
 
532
618
  def _parse_tweet(
@@ -9,9 +9,10 @@ This module provides comprehensive media upload functionality for Twitter API v2
9
9
  """
10
10
 
11
11
  import asyncio
12
+ import inspect
12
13
  import logging
13
14
  import os
14
- from collections.abc import Callable
15
+ from collections.abc import Awaitable, Callable
15
16
  from dataclasses import dataclass
16
17
  from enum import Enum
17
18
  from typing import Any, Literal
@@ -22,6 +23,7 @@ from marqetive.core.exceptions import (
22
23
  InvalidFileTypeError,
23
24
  MediaUploadError,
24
25
  )
26
+ from marqetive.core.models import ProgressEvent, ProgressStatus
25
27
  from marqetive.utils.file_handlers import download_file
26
28
  from marqetive.utils.media import (
27
29
  detect_mime_type,
@@ -30,6 +32,14 @@ from marqetive.utils.media import (
30
32
  )
31
33
  from marqetive.utils.retry import STANDARD_BACKOFF, retry_async
32
34
 
35
+ # Type aliases for progress callbacks
36
+ type SyncProgressCallback = Callable[[ProgressEvent], None]
37
+ type AsyncProgressCallback = Callable[[ProgressEvent], Awaitable[None]]
38
+ type ProgressCallback = SyncProgressCallback | AsyncProgressCallback
39
+
40
+ # Legacy callback type for backward compatibility
41
+ type LegacyProgressCallback = Callable[["UploadProgress"], None]
42
+
33
43
  logger = logging.getLogger(__name__)
34
44
 
35
45
  # Constants
@@ -76,6 +86,10 @@ SUPPORTED_GIF_TYPE = "image/gif"
76
86
  class UploadProgress:
77
87
  """Progress information for media upload.
78
88
 
89
+ .. deprecated:: 0.2.0
90
+ Use :class:`marqetive.core.models.ProgressEvent` instead.
91
+ This class will be removed in a future version.
92
+
79
93
  Attributes:
80
94
  media_id: Twitter media ID (if available).
81
95
  file_path: Path to file being uploaded.
@@ -136,13 +150,21 @@ class TwitterMediaManager:
136
150
  >>> manager = TwitterMediaManager(bearer_token="your_token")
137
151
  >>> result = await manager.upload_media("/path/to/image.jpg")
138
152
  >>> print(f"Media ID: {result.media_id}")
153
+
154
+ >>> # With progress callback
155
+ >>> def on_progress(event: ProgressEvent) -> None:
156
+ ... print(f"{event.operation}: {event.percentage:.1f}%")
157
+ >>> manager = TwitterMediaManager(
158
+ ... bearer_token="your_token",
159
+ ... progress_callback=on_progress,
160
+ ... )
139
161
  """
140
162
 
141
163
  def __init__(
142
164
  self,
143
165
  bearer_token: str,
144
166
  *,
145
- progress_callback: Callable[[UploadProgress], None] | None = None,
167
+ progress_callback: ProgressCallback | None = None,
146
168
  timeout: float = DEFAULT_REQUEST_TIMEOUT,
147
169
  ) -> None:
148
170
  """Initialize Twitter media manager.
@@ -150,6 +172,7 @@ class TwitterMediaManager:
150
172
  Args:
151
173
  bearer_token: Twitter OAuth 2.0 bearer token.
152
174
  progress_callback: Optional callback for progress updates.
175
+ Accepts ProgressEvent and can be sync or async.
153
176
  timeout: Request timeout in seconds.
154
177
  """
155
178
  self.bearer_token = bearer_token
@@ -163,6 +186,44 @@ class TwitterMediaManager:
163
186
  headers={"Authorization": f"Bearer {bearer_token}"},
164
187
  )
165
188
 
189
+ async def _emit_progress(
190
+ self,
191
+ status: ProgressStatus,
192
+ progress: int,
193
+ total: int,
194
+ message: str | None = None,
195
+ *,
196
+ entity_id: str | None = None,
197
+ file_path: str | None = None,
198
+ bytes_uploaded: int | None = None,
199
+ total_bytes: int | None = None,
200
+ ) -> None:
201
+ """Emit a progress update if a callback is registered.
202
+
203
+ Supports both sync and async callbacks.
204
+ """
205
+ if self.progress_callback is None:
206
+ return
207
+
208
+ event = ProgressEvent(
209
+ operation="upload_media",
210
+ platform="twitter",
211
+ status=status,
212
+ progress=progress,
213
+ total=total,
214
+ message=message,
215
+ entity_id=entity_id,
216
+ file_path=file_path,
217
+ bytes_uploaded=bytes_uploaded,
218
+ total_bytes=total_bytes,
219
+ )
220
+
221
+ result = self.progress_callback(event)
222
+
223
+ # If callback returned a coroutine, await it
224
+ if inspect.iscoroutine(result):
225
+ await result
226
+
166
227
  async def __aenter__(self) -> "TwitterMediaManager":
167
228
  """Enter async context."""
168
229
  return self
@@ -264,15 +325,15 @@ class TwitterMediaManager:
264
325
  file_size = os.path.getsize(file_path)
265
326
 
266
327
  # Notify upload start
267
- if self.progress_callback:
268
- progress = UploadProgress(
269
- media_id=None,
270
- file_path=file_path,
271
- bytes_uploaded=0,
272
- total_bytes=file_size,
273
- status="init",
274
- )
275
- self.progress_callback(progress)
328
+ await self._emit_progress(
329
+ status=ProgressStatus.INITIALIZING,
330
+ progress=0,
331
+ total=100,
332
+ message="Initializing upload",
333
+ file_path=file_path,
334
+ bytes_uploaded=0,
335
+ total_bytes=file_size,
336
+ )
276
337
 
277
338
  @retry_async(config=STANDARD_BACKOFF)
278
339
  async def _do_upload() -> MediaUploadResult:
@@ -290,15 +351,15 @@ class TwitterMediaManager:
290
351
  data["additional_owners"] = ",".join(additional_owners)
291
352
 
292
353
  # Notify upload in progress
293
- if self.progress_callback:
294
- progress = UploadProgress(
295
- media_id=None,
296
- file_path=file_path,
297
- bytes_uploaded=0,
298
- total_bytes=file_size,
299
- status="uploading",
300
- )
301
- self.progress_callback(progress)
354
+ await self._emit_progress(
355
+ status=ProgressStatus.UPLOADING,
356
+ progress=0,
357
+ total=100,
358
+ message="Uploading file",
359
+ file_path=file_path,
360
+ bytes_uploaded=0,
361
+ total_bytes=file_size,
362
+ )
302
363
 
303
364
  # Upload
304
365
  response = await self.client.post(
@@ -319,15 +380,16 @@ class TwitterMediaManager:
319
380
  )
320
381
 
321
382
  # Notify completion
322
- if self.progress_callback:
323
- progress = UploadProgress(
324
- media_id=media_id,
325
- file_path=file_path,
326
- bytes_uploaded=file_size,
327
- total_bytes=file_size,
328
- status="completed",
329
- )
330
- self.progress_callback(progress)
383
+ await self._emit_progress(
384
+ status=ProgressStatus.COMPLETED,
385
+ progress=100,
386
+ total=100,
387
+ message="Upload completed",
388
+ entity_id=media_id,
389
+ file_path=file_path,
390
+ bytes_uploaded=file_size,
391
+ total_bytes=file_size,
392
+ )
331
393
 
332
394
  logger.info(f"Simple upload completed: {media_id}")
333
395
  return result
@@ -388,15 +450,16 @@ class TwitterMediaManager:
388
450
  )
389
451
 
390
452
  # Notify upload start
391
- if self.progress_callback:
392
- progress = UploadProgress(
393
- media_id=media_id,
394
- file_path=file_path,
395
- bytes_uploaded=0,
396
- total_bytes=file_size,
397
- status="uploading",
398
- )
399
- self.progress_callback(progress)
453
+ await self._emit_progress(
454
+ status=ProgressStatus.UPLOADING,
455
+ progress=0,
456
+ total=100,
457
+ message="Starting chunked upload",
458
+ entity_id=media_id,
459
+ file_path=file_path,
460
+ bytes_uploaded=0,
461
+ total_bytes=file_size,
462
+ )
400
463
 
401
464
  # STEP 2: Upload chunks
402
465
  bytes_uploaded = 0
@@ -419,15 +482,17 @@ class TwitterMediaManager:
419
482
  segment_index += 1
420
483
 
421
484
  # Notify progress
422
- if self.progress_callback:
423
- progress = UploadProgress(
424
- media_id=media_id,
425
- file_path=file_path,
426
- bytes_uploaded=bytes_uploaded,
427
- total_bytes=file_size,
428
- status="uploading",
429
- )
430
- self.progress_callback(progress)
485
+ progress_pct = int((bytes_uploaded / file_size) * 100)
486
+ await self._emit_progress(
487
+ status=ProgressStatus.UPLOADING,
488
+ progress=progress_pct,
489
+ total=100,
490
+ message=f"Uploading chunk {segment_index}",
491
+ entity_id=media_id,
492
+ file_path=file_path,
493
+ bytes_uploaded=bytes_uploaded,
494
+ total_bytes=file_size,
495
+ )
431
496
 
432
497
  logger.debug(
433
498
  f"Uploaded chunk {segment_index}: "
@@ -443,15 +508,16 @@ class TwitterMediaManager:
443
508
  await self._wait_for_processing(result, file_path)
444
509
 
445
510
  # Notify completion
446
- if self.progress_callback:
447
- progress = UploadProgress(
448
- media_id=media_id,
449
- file_path=file_path,
450
- bytes_uploaded=file_size,
451
- total_bytes=file_size,
452
- status="completed",
453
- )
454
- self.progress_callback(progress)
511
+ await self._emit_progress(
512
+ status=ProgressStatus.COMPLETED,
513
+ progress=100,
514
+ total=100,
515
+ message="Chunked upload completed",
516
+ entity_id=media_id,
517
+ file_path=file_path,
518
+ bytes_uploaded=file_size,
519
+ total_bytes=file_size,
520
+ )
455
521
 
456
522
  logger.info(f"Chunked upload completed: {media_id}")
457
523
  return result
@@ -662,15 +728,17 @@ class TwitterMediaManager:
662
728
  )
663
729
 
664
730
  # Notify processing status
665
- if self.progress_callback:
666
- progress = UploadProgress(
667
- media_id=result.media_id,
668
- file_path=file_path,
669
- bytes_uploaded=os.path.getsize(file_path),
670
- total_bytes=os.path.getsize(file_path),
671
- status="processing",
672
- )
673
- self.progress_callback(progress)
731
+ file_size = os.path.getsize(file_path)
732
+ await self._emit_progress(
733
+ status=ProgressStatus.PROCESSING,
734
+ progress=90, # Show 90% during processing
735
+ total=100,
736
+ message=f"Processing media ({state})",
737
+ entity_id=result.media_id,
738
+ file_path=file_path,
739
+ bytes_uploaded=file_size,
740
+ total_bytes=file_size,
741
+ )
674
742
 
675
743
  await asyncio.sleep(check_after)
676
744
 
@@ -0,0 +1,58 @@
1
+ """Twitter/X-specific models for post creation.
2
+
3
+ This module defines Twitter-specific data models for creating tweets,
4
+ replies, quote tweets, and polls.
5
+ """
6
+
7
+ from pydantic import BaseModel, Field
8
+
9
+
10
+ class TwitterPostRequest(BaseModel):
11
+ """Twitter/X-specific post creation request.
12
+
13
+ Supports tweets, replies, quote tweets, and media attachments.
14
+ Twitter has a 280 character limit for text content.
15
+
16
+ Attributes:
17
+ content: Tweet text (max 280 characters)
18
+ media_urls: List of media URLs to attach (max 4 images or 1 video)
19
+ media_ids: List of pre-uploaded media IDs
20
+ reply_to_post_id: Tweet ID to reply to
21
+ quote_post_id: Tweet ID to quote
22
+ poll_options: List of poll options (2-4 options, each max 25 chars)
23
+ poll_duration_minutes: Poll duration in minutes (5-10080)
24
+ alt_texts: Alt text for each media item (for accessibility)
25
+
26
+ Example:
27
+ >>> # Simple tweet
28
+ >>> request = TwitterPostRequest(content="Hello Twitter!")
29
+
30
+ >>> # Reply to a tweet
31
+ >>> request = TwitterPostRequest(
32
+ ... content="Great point!",
33
+ ... reply_to_post_id="1234567890"
34
+ ... )
35
+
36
+ >>> # Quote tweet with media
37
+ >>> request = TwitterPostRequest(
38
+ ... content="Check this out!",
39
+ ... quote_post_id="1234567890",
40
+ ... media_urls=["https://example.com/image.jpg"]
41
+ ... )
42
+
43
+ >>> # Tweet with poll
44
+ >>> request = TwitterPostRequest(
45
+ ... content="What's your favorite?",
46
+ ... poll_options=["Option A", "Option B", "Option C"],
47
+ ... poll_duration_minutes=1440
48
+ ... )
49
+ """
50
+
51
+ content: str | None = None
52
+ media_urls: list[str] = Field(default_factory=list, max_length=4)
53
+ media_ids: list[str] = Field(default_factory=list, max_length=4)
54
+ reply_to_post_id: str | None = None
55
+ quote_post_id: str | None = None
56
+ poll_options: list[str] = Field(default_factory=list, max_length=4)
57
+ poll_duration_minutes: int | None = Field(default=None, ge=5, le=10080)
58
+ alt_texts: list[str] = Field(default_factory=list)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: marqetive-lib
3
- Version: 0.1.6
3
+ Version: 0.1.7
4
4
  Summary: Modern Python utilities for web APIs
5
5
  Keywords: api,utilities,web,http,marqetive
6
6
  Requires-Python: >=3.12
@@ -238,14 +238,6 @@ except PlatformError as e:
238
238
  print(f"Platform error: {e}")
239
239
  ```
240
240
 
241
- ## Requirements
242
-
243
- - Python 3.12+
244
- - httpx >= 0.28.1
245
- - pydantic >= 2.0.0
246
- - tweepy >= 4.16.0
247
- - aiofiles >= 24.0.0
248
-
249
241
  ## Development
250
242
 
251
243
  ### Setup Development Environment
@@ -0,0 +1,39 @@
1
+ marqetive/__init__.py,sha256=pW77CUnzOQ0X1pb-GTcRgrrvsSaJBdVhGZLnvCD_4q4,3032
2
+ marqetive/core/__init__.py,sha256=0_0vzxJ619YIJkz1yzSvhnGDJRkrErs_QSg2q3Bloss,1172
3
+ marqetive/core/base.py,sha256=J5iYXpa2C371zVLNMx3eFnC0fdLWqTrjbVcqJQdGyrU,16147
4
+ marqetive/core/client.py,sha256=2_FoNpqaRglsWg10i5RTbyDg_kRQKhgWjYs6iDdFxLg,3210
5
+ marqetive/core/exceptions.py,sha256=Xyj0bzNiZm5VTErmzXgVW8T6IQnOpF92-HJiKPKjIio,7076
6
+ marqetive/core/models.py,sha256=L2gA4FhW0feAXQFsz2ce1ttd0vScMRhatoTclhDGCU0,14727
7
+ marqetive/factory.py,sha256=irZ5oN8a__kXZH70UN2uI7TzqTXu66d4QZ1FoxSoiK8,14092
8
+ marqetive/platforms/__init__.py,sha256=RBxlQSGyELsulSnwf5uaE1ohxFc7jC61OO9CrKaZp48,1312
9
+ marqetive/platforms/instagram/__init__.py,sha256=c1Gs0ozG6D7Z-Uz_UQ7S3joL0qUTT9eUZPWcePyESk8,229
10
+ marqetive/platforms/instagram/client.py,sha256=C5T9v1Aina8F3_Dk3d_I_RiVt7VvxTwwqdYeizDr0iQ,25187
11
+ marqetive/platforms/instagram/exceptions.py,sha256=TcD_pX4eSx_k4yW8DgfA6SGPiAz3VW7cMqM8DmiXIhg,8978
12
+ marqetive/platforms/instagram/media.py,sha256=0ZbUbpwJ025_hccL9X8qced_-LJGoL_-NdS84Op97VE,23228
13
+ marqetive/platforms/instagram/models.py,sha256=20v3m1037y3b_WlsKF8zAOgV23nFu63tfmmUN1CefOI,2769
14
+ marqetive/platforms/linkedin/__init__.py,sha256=_FrdZpqcXjcUW6C-25zGV7poGih9yzs6y1AFnuizTUQ,1384
15
+ marqetive/platforms/linkedin/client.py,sha256=_5sNiu0YDYLh8rLKA_dv0Ggrja8z3dLbk9_oLzFQ2yc,56287
16
+ marqetive/platforms/linkedin/exceptions.py,sha256=i5fARUkZik46bS3htZBwUInVzetsZx1APpKEXLrCKf0,9762
17
+ marqetive/platforms/linkedin/media.py,sha256=iWXUfqDYGsrTqeM6CGZ7a8xjpbdJ5qESolQL8Fv2PIg,20341
18
+ marqetive/platforms/linkedin/models.py,sha256=n7DqwVxYSbGYBmeEJ1woCZ6XhUIHcLx8Gpm8uCBACzI,12620
19
+ marqetive/platforms/tiktok/__init__.py,sha256=BqjkXTZDyBlcY3lvREy13yP9h3RcDga8E6Rl6f5KPp8,238
20
+ marqetive/platforms/tiktok/client.py,sha256=i_nyhVywh4feFu5vv4LrMQOkoLsxfxgpH6aKa9JjdOc,17060
21
+ marqetive/platforms/tiktok/exceptions.py,sha256=vxwyAKujMGZJh0LetG1QsLF95QfUs_kR6ujsWSHGqL0,10124
22
+ marqetive/platforms/tiktok/media.py,sha256=nDijJYq89dQfMFwq58P2PXOvZukxgVRzMrfKTOONn_c,25717
23
+ marqetive/platforms/tiktok/models.py,sha256=acV-fe_3O6kKbZzqytCNCATAwmFpjt0Ac2uacbjt1u8,2822
24
+ marqetive/platforms/twitter/__init__.py,sha256=dvcgVT-v-JOtjSz-OUvxGrn_43OI6w_ep42Wx_nHTSM,217
25
+ marqetive/platforms/twitter/client.py,sha256=08jV2hQVmGOpnG3C05u7bCqL7KapWn7bSsG0wbN_t5M,23270
26
+ marqetive/platforms/twitter/exceptions.py,sha256=eZ-dJKOXH_-bAMg29zWKbEqMFud29piEJ5IWfC9wFts,8926
27
+ marqetive/platforms/twitter/media.py,sha256=_7ka0ENlKr6EMxQQvPS_A38_a8MpjDE2zIrXe20QkuI,27079
28
+ marqetive/platforms/twitter/models.py,sha256=yPQlx40SlNmz7YGasXUqdx7rEDEgrQ64aYovlPKo6oc,2126
29
+ marqetive/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
+ marqetive/utils/__init__.py,sha256=bSrNajbxYBSKQayrPviLz8JeGjplnyK8y_NGDtgb7yQ,977
31
+ marqetive/utils/file_handlers.py,sha256=4TP5kmWofNTSZmlS683CM1UYP83WvRd_NubMbqtXv-g,12568
32
+ marqetive/utils/helpers.py,sha256=8-ljhL47SremKcQO2GF8DIHOPODEv1rSioVNuSPCbec,2634
33
+ marqetive/utils/media.py,sha256=Rvxw9XKU65n-z4G1bEihG3wXZBmjSDZUqClfjGFrg6k,12013
34
+ marqetive/utils/oauth.py,sha256=LQLXpThZUe0XbSpO3dJ5oW3sPRJuKjSk3_f5_3baUzA,12095
35
+ marqetive/utils/retry.py,sha256=lAniJLMNWp9XsHrvU0XBNifpNEjfde4MGfd5hlFTPfA,7636
36
+ marqetive/utils/token_validator.py,sha256=dNvDeHs2Du5UyMMH2ZOW6ydR7OwOEKA4c9e-rG0f9-0,6698
37
+ marqetive_lib-0.1.7.dist-info/METADATA,sha256=xsPKt4AbFy44aZtNeft0YeaSWNKrS-xWxsavavh2xtM,7875
38
+ marqetive_lib-0.1.7.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
39
+ marqetive_lib-0.1.7.dist-info/RECORD,,
@@ -1,35 +0,0 @@
1
- marqetive/__init__.py,sha256=TPjbyZ8ZRux2b6GqSG_7w9A7auPaTkxlamcfYIz0XVw,2907
2
- marqetive/core/__init__.py,sha256=8n-Ys3qR4wcGUV2rZTz68ICknD1GrkYz82SxLo-dods,1129
3
- marqetive/core/base.py,sha256=CKNTA6nErZ_Fx8uPtWxgNY054kmSTlGXL81zaF2d0R0,13248
4
- marqetive/core/client.py,sha256=2_FoNpqaRglsWg10i5RTbyDg_kRQKhgWjYs6iDdFxLg,3210
5
- marqetive/core/exceptions.py,sha256=Xyj0bzNiZm5VTErmzXgVW8T6IQnOpF92-HJiKPKjIio,7076
6
- marqetive/core/models.py,sha256=W_yOuRWItWSn82n8vXRNN_ScdNkzY1De2qqXaVN2RGU,10974
7
- marqetive/factory.py,sha256=irZ5oN8a__kXZH70UN2uI7TzqTXu66d4QZ1FoxSoiK8,14092
8
- marqetive/platforms/__init__.py,sha256=RBxlQSGyELsulSnwf5uaE1ohxFc7jC61OO9CrKaZp48,1312
9
- marqetive/platforms/instagram/__init__.py,sha256=7ClfTovAcCHac2DzKS7z1MFuZpy9lcwet7YP5d6MPeY,135
10
- marqetive/platforms/instagram/client.py,sha256=C5T9v1Aina8F3_Dk3d_I_RiVt7VvxTwwqdYeizDr0iQ,25187
11
- marqetive/platforms/instagram/exceptions.py,sha256=TcD_pX4eSx_k4yW8DgfA6SGPiAz3VW7cMqM8DmiXIhg,8978
12
- marqetive/platforms/instagram/media.py,sha256=sZKbBpTac4hIR3OvVV3wL21uHOSQUUpBBKXrvC1zXPc,21161
13
- marqetive/platforms/linkedin/__init__.py,sha256=zCnokoPYs56iA1sBSYIlaZW2J50L3CbnQpJSaOLrzP8,131
14
- marqetive/platforms/linkedin/client.py,sha256=cU22ympiWxDPXSUIB0juAQUV3RCpBg-m2nb4D38N5Go,23806
15
- marqetive/platforms/linkedin/exceptions.py,sha256=i5fARUkZik46bS3htZBwUInVzetsZx1APpKEXLrCKf0,9762
16
- marqetive/platforms/linkedin/media.py,sha256=lYUKJWbI3mOsvdSOZfUytc4BWb_nIf4YjiKNpC7EpT0,16896
17
- marqetive/platforms/tiktok/__init__.py,sha256=BQtxdECd2bW9_vV9W-MY4A1rdXi_xurGWWmzTjTUpMM,123
18
- marqetive/platforms/tiktok/client.py,sha256=i_nyhVywh4feFu5vv4LrMQOkoLsxfxgpH6aKa9JjdOc,17060
19
- marqetive/platforms/tiktok/exceptions.py,sha256=vxwyAKujMGZJh0LetG1QsLF95QfUs_kR6ujsWSHGqL0,10124
20
- marqetive/platforms/tiktok/media.py,sha256=p42E0D3bp9x0RgdK7lqcBl2v5G70ZOpY4JTYS-oCgD4,23766
21
- marqetive/platforms/twitter/__init__.py,sha256=AA5BELRvZyl2WE_7-puSEWArxZjaXcTJ_i8NGOWrv6k,129
22
- marqetive/platforms/twitter/client.py,sha256=nVXFU1nZBimjzxq0uwCzi0hQy7tdkbW42bbV_A2w8jk,19627
23
- marqetive/platforms/twitter/exceptions.py,sha256=eZ-dJKOXH_-bAMg29zWKbEqMFud29piEJ5IWfC9wFts,8926
24
- marqetive/platforms/twitter/media.py,sha256=N8f9UZv1JPJoFDTrPOrvxqdShFU-DQPFBScBoCrZci4,24963
25
- marqetive/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
- marqetive/utils/__init__.py,sha256=bSrNajbxYBSKQayrPviLz8JeGjplnyK8y_NGDtgb7yQ,977
27
- marqetive/utils/file_handlers.py,sha256=4TP5kmWofNTSZmlS683CM1UYP83WvRd_NubMbqtXv-g,12568
28
- marqetive/utils/helpers.py,sha256=8-ljhL47SremKcQO2GF8DIHOPODEv1rSioVNuSPCbec,2634
29
- marqetive/utils/media.py,sha256=Rvxw9XKU65n-z4G1bEihG3wXZBmjSDZUqClfjGFrg6k,12013
30
- marqetive/utils/oauth.py,sha256=LQLXpThZUe0XbSpO3dJ5oW3sPRJuKjSk3_f5_3baUzA,12095
31
- marqetive/utils/retry.py,sha256=lAniJLMNWp9XsHrvU0XBNifpNEjfde4MGfd5hlFTPfA,7636
32
- marqetive/utils/token_validator.py,sha256=dNvDeHs2Du5UyMMH2ZOW6ydR7OwOEKA4c9e-rG0f9-0,6698
33
- marqetive_lib-0.1.6.dist-info/METADATA,sha256=Xf_dBnNYwqOSf9GHJuormIVzyb1oRAJI_zQOsebTOxE,7986
34
- marqetive_lib-0.1.6.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
35
- marqetive_lib-0.1.6.dist-info/RECORD,,