diff --git a/pyrogram/api/core/__init__.py b/pyrogram/api/core/__init__.py index b9ee0a98..078374f3 100644 --- a/pyrogram/api/core/__init__.py +++ b/pyrogram/api/core/__init__.py @@ -15,3 +15,11 @@ # # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . + +from .future_salt import FutureSalt +from .future_salts import FutureSalts +from .gzip_packed import GzipPacked +from .message import Message +from .msg_container import MsgContainer +from .object import Object +from .primitives import * diff --git a/pyrogram/api/core/future_salt.py b/pyrogram/api/core/future_salt.py new file mode 100644 index 00000000..e9697458 --- /dev/null +++ b/pyrogram/api/core/future_salt.py @@ -0,0 +1,40 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017 Dan Tès +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from datetime import datetime +from io import BytesIO + +from .object import Object +from .primitives import Int, Long + + +class FutureSalt(Object): + ID = 0x0949d9dc + + def __init__(self, valid_since: int or datetime, valid_until: int or datetime, salt: int): + self.valid_since = valid_since + self.valid_until = valid_until + self.salt = salt + + @staticmethod + def read(b: BytesIO) -> "FutureSalt": + valid_since = datetime.fromtimestamp(Int.read(b)) + valid_until = datetime.fromtimestamp(Int.read(b)) + salt = Long.read(b) + + return FutureSalt(valid_since, valid_until, salt) diff --git a/pyrogram/api/core/future_salts.py b/pyrogram/api/core/future_salts.py new file mode 100644 index 00000000..d1a62d95 --- /dev/null +++ b/pyrogram/api/core/future_salts.py @@ -0,0 +1,43 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017 Dan Tès +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from datetime import datetime +from io import BytesIO + +from . import FutureSalt +from .object import Object +from .primitives import Int, Long + + +class FutureSalts(Object): + ID = 0xae500895 + + def __init__(self, req_msg_id: int, now: int or datetime, salts: list): + self.req_msg_id = req_msg_id + self.now = now + self.salts = salts + + @staticmethod + def read(b: BytesIO) -> "FutureSalts": + req_msg_id = Long.read(b) + now = datetime.fromtimestamp(Int.read(b)) + + count = Int.read(b) + salts = [FutureSalt.read(b) for _ in range(count)] + + return FutureSalts(req_msg_id, now, salts) diff --git a/pyrogram/api/core/gzip_packed.py b/pyrogram/api/core/gzip_packed.py new file mode 100644 index 00000000..58d22760 --- /dev/null +++ b/pyrogram/api/core/gzip_packed.py @@ -0,0 +1,56 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017 Dan Tès +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from gzip import compress, decompress +from io import BytesIO + +from .object import Object +from .primitives import Int, Bytes + + +class GzipPacked(Object): + ID = 0x3072cfa1 + + def __init__(self, packed_data: Object): + self.packed_data = packed_data + + @staticmethod + def read(b: BytesIO) -> "GzipPacked": + # Return the Object itself instead of a GzipPacked wrapping it + return Object.read( + BytesIO( + decompress( + Bytes.read(b) + ) + ) + ) + + def write(self) -> bytes: + b = BytesIO() + + b.write(Int(self.ID, False)) + + b.write( + Bytes( + compress( + self.packed_data.write() + ) + ) + ) + + return b.getvalue() diff --git a/pyrogram/api/core/message.py b/pyrogram/api/core/message.py new file mode 100644 index 00000000..045c51bb --- /dev/null +++ b/pyrogram/api/core/message.py @@ -0,0 +1,51 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017 Dan Tès +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from io import BytesIO + +from .object import Object +from .primitives import Int, Long + + +class Message(Object): + ID = 0x5bb8e511 # hex(crc32(b"message msg_id:long seqno:int bytes:int body:Object = Message")) + + def __init__(self, body: Object, msg_id: int, seq_no: int, length: int): + self.msg_id = msg_id + self.seq_no = seq_no + self.length = length + self.body = body + + @staticmethod + def read(b: BytesIO) -> "Message": + msg_id = Long.read(b) + seq_no = Int.read(b) + length = Int.read(b) + body = b.read(length) + + return Message(Object.read(BytesIO(body)), msg_id, seq_no, length) + + def write(self) -> bytes: + b = BytesIO() + + b.write(Long(self.msg_id)) + b.write(Int(self.seq_no)) + b.write(Int(self.length)) + b.write(self.body.write()) + + return b.getvalue() diff --git a/pyrogram/api/core/msg_container.py b/pyrogram/api/core/msg_container.py new file mode 100644 index 00000000..57286cd6 --- /dev/null +++ b/pyrogram/api/core/msg_container.py @@ -0,0 +1,48 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017 Dan Tès +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from io import BytesIO + +from .message import Message +from .object import Object +from .primitives import Int + + +class MsgContainer(Object): + ID = 0x73f1f8dc + + def __init__(self, messages: list): + self.messages = messages + + @staticmethod + def read(b: BytesIO) -> "MsgContainer": + count = Int.read(b) + return MsgContainer([Message.read(b) for _ in range(count)]) + + def write(self) -> bytes: + b = BytesIO() + + b.write(Int(self.ID, False)) + + count = len(self.messages) + b.write(Int(count)) + + for message in self.messages: + b.write(message.write()) + + return b.getvalue() diff --git a/pyrogram/api/core/object.py b/pyrogram/api/core/object.py new file mode 100644 index 00000000..72452c46 --- /dev/null +++ b/pyrogram/api/core/object.py @@ -0,0 +1,69 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017 Dan Tès +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from collections import OrderedDict +from datetime import datetime +from importlib import import_module +from io import BytesIO +from json import JSONEncoder, dumps + +from ..all import objects + + +class Object: + @staticmethod + def read(b: BytesIO, *args): + id = int.from_bytes(b.read(4), "little") + name = objects.get(id) + path, name = name.rsplit(".", 1) + + return getattr( + import_module("pyrogram.api." + path), + name + ).read(b, *args) + + def write(self, *args) -> bytes: + pass + + def __str__(self) -> str: + return dumps(self, cls=Encoder, indent=4) + + def __eq__(self, other) -> bool: + return self.__dict__ == other.__dict__ + + def __len__(self) -> int: + return len(self.write()) + + def __call__(self): + pass + + +class Encoder(JSONEncoder): + def default(self, o: Object): + try: + content = o.__dict__ + except AttributeError: + if isinstance(o, datetime): + return o.strftime("%d-%b-%Y %H:%M:%S") + else: + return repr(o) + + return OrderedDict( + [("_", objects.get(getattr(o, "ID", None), None))] + + [i for i in content.items()] + )