marqetive-lib 0.1.8__tar.gz → 0.1.9__tar.gz

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 (39) hide show
  1. {marqetive_lib-0.1.8 → marqetive_lib-0.1.9}/PKG-INFO +1 -1
  2. {marqetive_lib-0.1.8 → marqetive_lib-0.1.9}/pyproject.toml +1 -1
  3. {marqetive_lib-0.1.8 → marqetive_lib-0.1.9}/src/marqetive/platforms/tiktok/client.py +19 -8
  4. {marqetive_lib-0.1.8 → marqetive_lib-0.1.9}/src/marqetive/platforms/tiktok/media.py +33 -4
  5. {marqetive_lib-0.1.8 → marqetive_lib-0.1.9}/README.md +0 -0
  6. {marqetive_lib-0.1.8 → marqetive_lib-0.1.9}/src/marqetive/__init__.py +0 -0
  7. {marqetive_lib-0.1.8 → marqetive_lib-0.1.9}/src/marqetive/core/__init__.py +0 -0
  8. {marqetive_lib-0.1.8 → marqetive_lib-0.1.9}/src/marqetive/core/base.py +0 -0
  9. {marqetive_lib-0.1.8 → marqetive_lib-0.1.9}/src/marqetive/core/client.py +0 -0
  10. {marqetive_lib-0.1.8 → marqetive_lib-0.1.9}/src/marqetive/core/exceptions.py +0 -0
  11. {marqetive_lib-0.1.8 → marqetive_lib-0.1.9}/src/marqetive/core/models.py +0 -0
  12. {marqetive_lib-0.1.8 → marqetive_lib-0.1.9}/src/marqetive/factory.py +0 -0
  13. {marqetive_lib-0.1.8 → marqetive_lib-0.1.9}/src/marqetive/platforms/__init__.py +0 -0
  14. {marqetive_lib-0.1.8 → marqetive_lib-0.1.9}/src/marqetive/platforms/instagram/__init__.py +0 -0
  15. {marqetive_lib-0.1.8 → marqetive_lib-0.1.9}/src/marqetive/platforms/instagram/client.py +0 -0
  16. {marqetive_lib-0.1.8 → marqetive_lib-0.1.9}/src/marqetive/platforms/instagram/exceptions.py +0 -0
  17. {marqetive_lib-0.1.8 → marqetive_lib-0.1.9}/src/marqetive/platforms/instagram/media.py +0 -0
  18. {marqetive_lib-0.1.8 → marqetive_lib-0.1.9}/src/marqetive/platforms/instagram/models.py +0 -0
  19. {marqetive_lib-0.1.8 → marqetive_lib-0.1.9}/src/marqetive/platforms/linkedin/__init__.py +0 -0
  20. {marqetive_lib-0.1.8 → marqetive_lib-0.1.9}/src/marqetive/platforms/linkedin/client.py +0 -0
  21. {marqetive_lib-0.1.8 → marqetive_lib-0.1.9}/src/marqetive/platforms/linkedin/exceptions.py +0 -0
  22. {marqetive_lib-0.1.8 → marqetive_lib-0.1.9}/src/marqetive/platforms/linkedin/media.py +0 -0
  23. {marqetive_lib-0.1.8 → marqetive_lib-0.1.9}/src/marqetive/platforms/linkedin/models.py +0 -0
  24. {marqetive_lib-0.1.8 → marqetive_lib-0.1.9}/src/marqetive/platforms/tiktok/__init__.py +0 -0
  25. {marqetive_lib-0.1.8 → marqetive_lib-0.1.9}/src/marqetive/platforms/tiktok/exceptions.py +0 -0
  26. {marqetive_lib-0.1.8 → marqetive_lib-0.1.9}/src/marqetive/platforms/tiktok/models.py +0 -0
  27. {marqetive_lib-0.1.8 → marqetive_lib-0.1.9}/src/marqetive/platforms/twitter/__init__.py +0 -0
  28. {marqetive_lib-0.1.8 → marqetive_lib-0.1.9}/src/marqetive/platforms/twitter/client.py +0 -0
  29. {marqetive_lib-0.1.8 → marqetive_lib-0.1.9}/src/marqetive/platforms/twitter/exceptions.py +0 -0
  30. {marqetive_lib-0.1.8 → marqetive_lib-0.1.9}/src/marqetive/platforms/twitter/media.py +0 -0
  31. {marqetive_lib-0.1.8 → marqetive_lib-0.1.9}/src/marqetive/platforms/twitter/models.py +0 -0
  32. {marqetive_lib-0.1.8 → marqetive_lib-0.1.9}/src/marqetive/py.typed +0 -0
  33. {marqetive_lib-0.1.8 → marqetive_lib-0.1.9}/src/marqetive/utils/__init__.py +0 -0
  34. {marqetive_lib-0.1.8 → marqetive_lib-0.1.9}/src/marqetive/utils/file_handlers.py +0 -0
  35. {marqetive_lib-0.1.8 → marqetive_lib-0.1.9}/src/marqetive/utils/helpers.py +0 -0
  36. {marqetive_lib-0.1.8 → marqetive_lib-0.1.9}/src/marqetive/utils/media.py +0 -0
  37. {marqetive_lib-0.1.8 → marqetive_lib-0.1.9}/src/marqetive/utils/oauth.py +0 -0
  38. {marqetive_lib-0.1.8 → marqetive_lib-0.1.9}/src/marqetive/utils/retry.py +0 -0
  39. {marqetive_lib-0.1.8 → marqetive_lib-0.1.9}/src/marqetive/utils/token_validator.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: marqetive-lib
3
- Version: 0.1.8
3
+ Version: 0.1.9
4
4
  Summary: Modern Python utilities for web APIs
5
5
  Keywords: api,utilities,web,http,marqetive
6
6
  Requires-Python: >=3.12
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
4
4
 
5
5
  [project]
6
6
  name = "marqetive-lib"
7
- version = "0.1.8"
7
+ version = "0.1.9"
8
8
  description = "Modern Python utilities for web APIs"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12"
@@ -231,15 +231,26 @@ class TikTokClient(SocialMediaPlatform):
231
231
  wait_for_publish=True,
232
232
  )
233
233
 
234
- if not upload_result.video_id:
235
- raise PlatformError(
236
- "Video upload succeeded but no video ID returned. "
237
- "Video may still be processing.",
238
- platform=self.platform_name,
239
- )
234
+ # 4. Return post - either fetch full details or create minimal Post
235
+ if upload_result.video_id:
236
+ # Fetch the created post to return full Post object
237
+ return await self.get_post(upload_result.video_id)
240
238
 
241
- # 4. Fetch the created post to return full Post object
242
- return await self.get_post(upload_result.video_id)
239
+ # For private/SELF_ONLY posts, TikTok may not return video_id
240
+ # Return a minimal Post object with publish_id
241
+ return Post(
242
+ post_id=upload_result.publish_id,
243
+ platform=self.platform_name,
244
+ content=request.content,
245
+ status=PostStatus.PUBLISHED,
246
+ created_at=datetime.now(),
247
+ raw_data={
248
+ "publish_id": upload_result.publish_id,
249
+ "upload_status": upload_result.status,
250
+ "privacy_level": privacy_level.value,
251
+ "note": "Video published but video_id not returned (common for private posts)",
252
+ },
253
+ )
243
254
 
244
255
  async def get_post(self, post_id: str) -> Post:
245
256
  """Retrieve a TikTok video by its ID.
@@ -531,12 +531,22 @@ class TikTokMediaManager:
531
531
  result_data = data.get("data", {})
532
532
  status = result_data.get("status", PublishStatus.FAILED)
533
533
 
534
+ logger.debug(f"TikTok publish status response: {data}")
535
+
534
536
  video_id = None
535
537
  if status == PublishStatus.PUBLISH_COMPLETE:
536
- # Video IDs are in publicaly_available_post_id array
538
+ # Video IDs are in publicaly_available_post_id array (note TikTok's typo)
539
+ # For private/SELF_ONLY posts, this may be empty
537
540
  video_ids = result_data.get("publicaly_available_post_id", [])
538
541
  if video_ids:
539
542
  video_id = str(video_ids[0])
543
+ else:
544
+ # Try alternative field names that TikTok might use
545
+ video_id = result_data.get("video_id") or result_data.get("item_id")
546
+ logger.warning(
547
+ f"No video ID in publicaly_available_post_id, "
548
+ f"tried alternatives: video_id={video_id}"
549
+ )
540
550
 
541
551
  return MediaUploadResult(
542
552
  publish_id=publish_id,
@@ -713,6 +723,11 @@ class TikTokMediaManager:
713
723
  def _normalize_chunk_size(self, chunk_size: int, file_size: int) -> int:
714
724
  """Normalize chunk size to TikTok's requirements.
715
725
 
726
+ TikTok chunk requirements:
727
+ - Minimum chunk size: 5MB (except for files smaller than 5MB)
728
+ - Maximum chunk size: 64MB (final chunk can be up to 128MB)
729
+ - All non-final chunks must be at least MIN_CHUNK_SIZE
730
+
716
731
  Args:
717
732
  chunk_size: Requested chunk size.
718
733
  file_size: Total file size.
@@ -720,13 +735,27 @@ class TikTokMediaManager:
720
735
  Returns:
721
736
  Normalized chunk size within TikTok limits.
722
737
  """
723
- # Files smaller than MIN_CHUNK_SIZE must be uploaded as single chunk
724
- if file_size < MIN_CHUNK_SIZE:
738
+ # Files smaller than MAX_CHUNK_SIZE (64MB) should be uploaded as single chunk
739
+ # This avoids issues with the final chunk being smaller than MIN_CHUNK_SIZE
740
+ if file_size <= MAX_CHUNK_SIZE:
725
741
  return file_size
726
742
 
727
- # Ensure within limits
743
+ # For larger files, ensure chunk size is within limits
728
744
  chunk_size = max(MIN_CHUNK_SIZE, min(chunk_size, MAX_CHUNK_SIZE))
729
745
 
746
+ # Ensure the last chunk won't be smaller than MIN_CHUNK_SIZE
747
+ # If it would be, increase chunk size to make fewer, larger chunks
748
+ total_chunks = math.ceil(file_size / chunk_size)
749
+ last_chunk_size = file_size - (chunk_size * (total_chunks - 1))
750
+
751
+ if last_chunk_size < MIN_CHUNK_SIZE and total_chunks > 1:
752
+ # Recalculate to have fewer chunks with larger size
753
+ # Use ceiling division to ensure last chunk is large enough
754
+ total_chunks = math.ceil(file_size / MAX_CHUNK_SIZE)
755
+ chunk_size = math.ceil(file_size / total_chunks)
756
+ # Ensure still within limits
757
+ chunk_size = max(MIN_CHUNK_SIZE, min(chunk_size, MAX_CHUNK_SIZE))
758
+
730
759
  return chunk_size
731
760
 
732
761
  def _validate_media(self, mime_type: str, file_size: int) -> None:
File without changes