import pyrogram import json import typing from .mtproto_task_abstraction import MtProtoTask from .webhook import WebHookDataForward from pyrogram.api.types import ChannelMessagesFilterEmpty from pyrogram.api.types.updates import ChannelDifference, ChannelDifferenceTooLong, ChannelDifferenceEmpty from pyrogram.api.functions.updates.get_channel_difference import GetChannelDifference from pyrogram.client.types.messages_and_media import Message as MessagePyrogram class JsonSerializerFixes: @staticmethod def user(obj): obj.type = "private" return obj @staticmethod def user_type(obj): obj.type = "channel" if obj.id < 0 else "private" return obj class JsonSerializer: fixes = { "from_user": { "new_name": "from", "patch": JsonSerializerFixes.user }, "user": { "new_name": "user", "patch": JsonSerializerFixes.user_type } } @staticmethod def default(obj): if isinstance(obj, bytes): return repr(obj) cls = JsonSerializer result = {} for name in filter(lambda x: not x.startswith("_"), obj.__dict__): value = getattr(obj, name) if value is None: continue if name in cls.fixes: value = cls.fixes[name]["patch"](value) name = cls.fixes[name]["new_name"] result[name] = value return result class ChannelHistoryReadTask(MtProtoTask): _channel: pyrogram.Chat _client: pyrogram.Client _pts: int _webhook: str def setup(self, client: pyrogram.Client, channel: pyrogram.Chat, webhook: str): self._pts = False self._client = client self._channel = channel self._webhook = webhook async def process(self) -> typing.Union[bool, int]: response = await self._client.send( GetChannelDifference( channel=self._channel, filter=ChannelMessagesFilterEmpty(), pts=self._pts if self._pts else 0xFFFFFFF, limit=0xFFFFFFF, force=True ) ) if isinstance(response, ChannelDifference): self._pts = response.pts users = {i.id: i for i in response.users} chats = {i.id: i for i in response.chats} for message in response.new_messages: message = await MessagePyrogram._parse(self._client, message, users, chats) data = json.dumps( {"update_id": 1, "message": message}, default=JsonSerializer.default, ensure_ascii=True, allow_nan=False, check_circular=True, sort_keys=False ) forwarder = WebHookDataForward() forwarder.setup(self._webhook, data) await self.future(forwarder) if not response.final: return 1 return response.timeout if isinstance(response, ChannelDifferenceEmpty): self._pts = response.pts return response.timeout if isinstance(response, ChannelDifferenceTooLong): return False