فهرست منبع

Add image uploading and rename stuff

Tulir Asokan 4 سال پیش
والد
کامیت
89379085c8
6فایلهای تغییر یافته به همراه89 افزوده شده و 5 حذف شده
  1. 3 2
      mauigpapi/http/api.py
  2. 4 3
      mauigpapi/http/base.py
  3. 0 0
      mauigpapi/http/direct_inbox.py
  4. 54 0
      mauigpapi/http/upload.py
  5. 1 0
      mauigpapi/types/__init__.py
  6. 27 0
      mauigpapi/types/upload.py

+ 3 - 2
mauigpapi/http/api.py

@@ -1,6 +1,7 @@
-from .direct_inbox_feed import DirectInboxAPI
+from .direct_inbox import DirectInboxAPI
 from .login_simulate import LoginSimulateAPI
 from .login_simulate import LoginSimulateAPI
+from .upload import UploadAPI
 
 
 
 
-class AndroidAPI(DirectInboxAPI, LoginSimulateAPI):
+class AndroidAPI(DirectInboxAPI, LoginSimulateAPI, UploadAPI):
     pass
     pass

+ 4 - 3
mauigpapi/http/base.py

@@ -90,12 +90,13 @@ class BaseAndroidAPI:
         }
         }
         return {k: v for k, v in headers.items() if v is not None}
         return {k: v for k, v in headers.items() if v is not None}
 
 
-    async def std_http_post(self, path: str, data: Optional[JSON] = None,
+    async def std_http_post(self, path: str, data: Optional[JSON] = None, raw: bool = False,
                             filter_nulls: bool = False, headers: Optional[Dict[str, str]] = None,
                             filter_nulls: bool = False, headers: Optional[Dict[str, str]] = None,
                             response_type: Optional[Type[T]] = JSON) -> T:
                             response_type: Optional[Type[T]] = JSON) -> T:
         headers = {**self.headers, **headers} if headers else self.headers
         headers = {**self.headers, **headers} if headers else self.headers
-        resp = await self.http.post(url=self.url.with_path(path), headers=headers,
-                                    data=self.sign(data, filter_nulls=filter_nulls))
+        if not raw:
+            data = self.sign(data, filter_nulls=filter_nulls)
+        resp = await self.http.post(url=self.url.with_path(path), headers=headers, data=data)
         print(f"{path} response: {await resp.text()}")
         print(f"{path} response: {await resp.text()}")
         if response_type is str or response_type is None:
         if response_type is str or response_type is None:
             self._handle_response_headers(resp)
             self._handle_response_headers(resp)

+ 0 - 0
mauigpapi/http/direct_inbox_feed.py → mauigpapi/http/direct_inbox.py


+ 54 - 0
mauigpapi/http/upload.py

@@ -0,0 +1,54 @@
+# mautrix-instagram - A Matrix-Instagram puppeting bridge.
+# Copyright (C) 2020 Tulir Asokan
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <https://www.gnu.org/licenses/>.
+from typing import Optional, Dict, Any
+from uuid import uuid4
+import random
+import time
+import json
+
+from .base import BaseAndroidAPI
+from ..types import UploadPhotoResponse
+
+
+class UploadAPI(BaseAndroidAPI):
+    async def upload_jpeg_photo(self, data: bytes, upload_id: Optional[str] = None,
+                                is_sidecar: bool = False, waterfall_id: Optional[str] = None,
+                                media_type: int = 1) -> UploadPhotoResponse:
+        upload_id = upload_id or str(time.time())
+        name = f"{upload_id}_0_{random.randint(1000000000, 9999999999)}"
+        params = {
+            "retry_context": json.dumps(
+                {"num_step_auto_retry": 0, "num_reupload": 0, "num_step_manual_retry": 0}),
+            # TODO enum?
+            "media_type": str(media_type),
+            "upload_id": upload_id,
+            "xsharing_user_ids": json.dumps([]),
+            "image_compression": json.dumps(
+                {"lib_name": "moz", "lib_version": "3.1.m", "quality": 80}),
+        }
+        if is_sidecar:
+            params["is_sidecar"] = "1"
+        headers = {
+            "X_FB_PHOTO_WATERFALL_ID": waterfall_id or str(uuid4()),
+            "X-Entity-Type": "image/jpeg",
+            "Offset": "0",
+            "X-Instagram-Rupload-Params": json.dumps(params),
+            "X-Entity-Name": name,
+            "X-Entity-Length": str(len(data)),
+            "Content-Type": "application/octet-stream",
+        }
+        return await self.std_http_post(f"/rupload_igphoto/{name}", headers=headers, data=data,
+                                        raw=True, response_type=UploadPhotoResponse)

+ 1 - 0
mauigpapi/types/__init__.py

@@ -5,3 +5,4 @@ from .error import (SpamResponse, CheckpointResponse, CheckpointChallenge,
 from .login import LoginResponseUser, LoginResponseNametag, LoginResponse, LogoutResponse
 from .login import LoginResponseUser, LoginResponseNametag, LoginResponse, LogoutResponse
 from .account import CurrentUser, EntityText, HDProfilePictureVersion, CurrentUserResponse
 from .account import CurrentUser, EntityText, HDProfilePictureVersion, CurrentUserResponse
 from .direct_inbox import DirectInboxResponse
 from .direct_inbox import DirectInboxResponse
+from .upload import UploadPhotoResponse

+ 27 - 0
mauigpapi/types/upload.py

@@ -0,0 +1,27 @@
+# mautrix-instagram - A Matrix-Instagram puppeting bridge.
+# Copyright (C) 2020 Tulir Asokan
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <https://www.gnu.org/licenses/>.
+from typing import Any
+
+from attr import dataclass
+
+from mautrix.types import SerializableAttrs
+
+
+@dataclass
+class UploadPhotoResponse(SerializableAttrs['UploadPhotoResponse']):
+    upload_id: str
+    status: str
+    xsharing_nonces: Any