|
5 | 5 | from json import JSONDecodeError |
6 | 6 | from pathlib import Path |
7 | 7 | import string |
| 8 | +import datetime |
8 | 9 | import json |
9 | 10 | from .parser.ProfileParser import parse_profile |
10 | | -from .structures import Profile |
| 11 | +from .structures import Profile, StoryLink |
11 | 12 | from .Direct import Direct |
12 | 13 | from ensta.Utils import time_id, fb_uploader |
13 | 14 |
|
@@ -411,3 +412,107 @@ def unblock(self, user_id: str) -> bool: |
411 | 412 | "Unable to unblock. Is the user_id correct? Username should not be used. Try using another account, switch " |
412 | 413 | "to a different network, or use reputed proxies." |
413 | 414 | ) |
| 415 | + |
| 416 | + def upload_story( |
| 417 | + self, |
| 418 | + upload_id: str, |
| 419 | + resolution: tuple[int, int] = (1080, 1920), |
| 420 | + entities: list[StoryLink] = None |
| 421 | + ) -> bool: |
| 422 | + """ |
| 423 | + Uploads media to story |
| 424 | + :param upload_id: Returned by get_upload_id(media_path) |
| 425 | + :param resolution: Resolution (Width, Height) of device canvas |
| 426 | + :param entities: Entities like stickers, links etc. |
| 427 | + :return: Boolean (Uploaded or not) |
| 428 | + """ |
| 429 | + |
| 430 | + date = datetime.datetime.now() |
| 431 | + |
| 432 | + data: dict = { |
| 433 | + "supported_capabilities_new": "[{\"name\":\"SUPPORTED_SDK_VERSIONS\",\"value\":\"131.0,132.0,133.0,134.0,135.0,136.0,137.0,138.0,139.0,140.0,141.0,142.0,143.0,144.0,145.0,146.0,147.0,148.0,149.0,150.0,151.0,152.0,153.0,154.0,155.0,156.0,157.0,158.0,159.0\"},{\"name\":\"FACE_TRACKER_VERSION\",\"value\":\"14\"},{\"name\":\"COMPRESSION\",\"value\":\"ETC2_COMPRESSION\"},{\"name\":\"gyroscope\",\"value\":\"gyroscope_enabled\"}]", |
| 434 | + "has_original_sound": "1", |
| 435 | + "camera_entry_point": "12", |
| 436 | + "original_media_type": "1", |
| 437 | + "camera_session_id": str(uuid4()), |
| 438 | + "date_time_digitalized": f"{date.year}:{date.month:02}:{date.day:02} {date.hour:02}:{date.minute:02}:{date.second:02}", |
| 439 | + "camera_model": "sdk_gphone64_x86_64", |
| 440 | + "scene_capture_type": "", |
| 441 | + "timezone_offset": (datetime.datetime.fromtimestamp(date.timestamp() * 1e-3) - datetime.datetime.utcfromtimestamp(date.timestamp() * 1e-3)).seconds, |
| 442 | + "client_shared_at": int(date.timestamp()), |
| 443 | + "story_sticker_ids": "link_sticker_default", |
| 444 | + "configure_mode": "1", |
| 445 | + "source_type": "3", |
| 446 | + "camera_position": "front", |
| 447 | + "_uid": self.user_id, |
| 448 | + "device_id": self.device_id, |
| 449 | + "composition_id": str(uuid4()), |
| 450 | + "_uuid": self.phone_id, |
| 451 | + "creation_surface": "camera", |
| 452 | + "can_play_spotify_audio": "1", |
| 453 | + "date_time_original": f"{date.year}:{date.month:02}:{date.day:02} {date.hour:02}:{date.minute:02}:{date.second:02}", |
| 454 | + "capture_type": "normal", |
| 455 | + "upload_id": upload_id, |
| 456 | + "client_timestamp": int(date.timestamp()), |
| 457 | + "private_mention_sharing_enabled": "1", |
| 458 | + "media_transformation_info": f"{{\"width\":\"{resolution[0]}\",\"height\":\"{resolution[1]}\",\"x_transform\":\"0\",\"y_transform\":\"0\",\"zoom\":\"1.0\",\"rotation\":\"0.0\",\"background_coverage\":\"0.0\"}}", |
| 459 | + "camera_make": "Google", |
| 460 | + "device": { |
| 461 | + "manufacturer": "Google", |
| 462 | + "model": "sdk_gphone64_x86_64", |
| 463 | + "android_version": 31, |
| 464 | + "android_release": "12" |
| 465 | + }, |
| 466 | + "edits": { |
| 467 | + "filter_type": 0, |
| 468 | + "filter_strength": 1.0, |
| 469 | + "crop_original_size": [ |
| 470 | + float(resolution[0]), |
| 471 | + float(resolution[1]) |
| 472 | + ] |
| 473 | + }, |
| 474 | + "extra": { |
| 475 | + "source_width": resolution[0], |
| 476 | + "source_height": resolution[1] |
| 477 | + } |
| 478 | + } |
| 479 | + |
| 480 | + tap_models: list[dict] = [] |
| 481 | + |
| 482 | + if entities is not None: |
| 483 | + for entity in entities: |
| 484 | + |
| 485 | + # A Story Link? |
| 486 | + if isinstance(entity, StoryLink): |
| 487 | + tap_models.append( |
| 488 | + { |
| 489 | + "x": entity.x, |
| 490 | + "y": entity.y, |
| 491 | + "z": entity.z, |
| 492 | + "width": entity.width, |
| 493 | + "height": entity.height, |
| 494 | + "rotation": entity.rotation, |
| 495 | + "type": entity.type, |
| 496 | + "link_type": entity.link_type, |
| 497 | + "custom_cta": entity.title if entity.title != "" else entity.url, |
| 498 | + "url": entity.url, |
| 499 | + "is_sticker": entity.is_sticker, |
| 500 | + "tap_state": entity.tap_state, |
| 501 | + "tap_state_str_id": entity.tap_state_str_id, |
| 502 | + } |
| 503 | + ) |
| 504 | + |
| 505 | + if len(tap_models) > 0: data["tap_models"] = tap_models |
| 506 | + |
| 507 | + response: Response = self.session.post( |
| 508 | + url="https://i.instagram.com/api/v1/media/configure_to_story/", |
| 509 | + data={"signed_body": "SIGNATURE." + json.dumps(data)} |
| 510 | + ) |
| 511 | + |
| 512 | + try: return response.json().get("status", "") == "ok" |
| 513 | + |
| 514 | + except JSONDecodeError: |
| 515 | + raise NetworkError( |
| 516 | + "Failed to publish story. Is your media correct? Are all entities correct? " |
| 517 | + "Maybe you're being rate limited, try using a different account." |
| 518 | + ) |
0 commit comments