| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | import contextlib |
| | import inspect |
| | import sys |
| | import time |
| | from logging import Logger |
| |
|
| | from telethonpatch import TelegramClient |
| | from telethon import utils as telethon_utils |
| | from telethon.errors import ( |
| | AccessTokenExpiredError, |
| | AccessTokenInvalidError, |
| | ApiIdInvalidError, |
| | AuthKeyDuplicatedError, |
| | ) |
| |
|
| | from ..configs import Var |
| | from . import * |
| |
|
| |
|
| | class UltroidClient(TelegramClient): |
| | def __init__( |
| | self, |
| | session, |
| | api_id=None, |
| | api_hash=None, |
| | bot_token=None, |
| | udB=None, |
| | logger: Logger = LOGS, |
| | log_attempt=True, |
| | exit_on_error=True, |
| | *args, |
| | **kwargs, |
| | ): |
| | self._cache = {} |
| | self._dialogs = [] |
| | self._handle_error = exit_on_error |
| | self._log_at = log_attempt |
| | self.logger = logger |
| | self.udB = udB |
| | kwargs["api_id"] = api_id or Var.API_ID |
| | kwargs["api_hash"] = api_hash or Var.API_HASH |
| | kwargs["base_logger"] = TelethonLogger |
| | super().__init__(session, **kwargs) |
| | self.run_in_loop(self.start_client(bot_token=bot_token)) |
| | self.dc_id = self.session.dc_id |
| |
|
| | def __repr__(self): |
| | return f"<Ultroid.Client :\n self: {self.full_name}\n bot: {self._bot}\n>" |
| |
|
| | @property |
| | def __dict__(self): |
| | if self.me: |
| | return self.me.to_dict() |
| |
|
| | async def start_client(self, **kwargs): |
| | """function to start client""" |
| | if self._log_at: |
| | self.logger.info("Trying to login.") |
| | try: |
| | await self.start(**kwargs) |
| | except ApiIdInvalidError: |
| | self.logger.critical("API ID and API_HASH combination does not match!") |
| |
|
| | sys.exit() |
| | except (AuthKeyDuplicatedError, EOFError) as er: |
| | if self._handle_error: |
| | self.logger.critical("String session expired. Create new!") |
| | return sys.exit() |
| | self.logger.critical("String session expired.") |
| | except (AccessTokenExpiredError, AccessTokenInvalidError): |
| | |
| | |
| | self.udB.del_key("BOT_TOKEN") |
| | self.logger.critical( |
| | "Bot token is expired or invalid. Create new from @Botfather and add in BOT_TOKEN env variable!" |
| | ) |
| | sys.exit() |
| | |
| | self.me = await self.get_me() |
| | if self.me.bot: |
| | me = f"@{self.me.username}" |
| | else: |
| | setattr(self.me, "phone", None) |
| | me = self.full_name |
| | if self._log_at: |
| | self.logger.info(f"Logged in as {me}") |
| | self._bot = await self.is_bot() |
| |
|
| | async def fast_uploader(self, file, **kwargs): |
| | """Upload files in a faster way""" |
| |
|
| | import os |
| | from pathlib import Path |
| |
|
| | start_time = time.time() |
| | path = Path(file) |
| | filename = kwargs.get("filename", path.name) |
| | |
| | show_progress = kwargs.get("show_progress", False) |
| | if show_progress: |
| | event = kwargs["event"] |
| | |
| | use_cache = kwargs.get("use_cache", True) |
| | |
| | to_delete = kwargs.get("to_delete", False) |
| | message = kwargs.get("message", f"Uploading {filename}...") |
| | by_bot = self._bot |
| | size = os.path.getsize(file) |
| | |
| | if size < 5 * 2 ** 20: |
| | show_progress = False |
| | if use_cache and self._cache and self._cache.get("upload_cache"): |
| | for files in self._cache["upload_cache"]: |
| | if ( |
| | files["size"] == size |
| | and files["path"] == path |
| | and files["name"] == filename |
| | and files["by_bot"] == by_bot |
| | ): |
| | if to_delete: |
| | with contextlib.suppress(FileNotFoundError): |
| | os.remove(file) |
| | return files["raw_file"], time.time() - start_time |
| |
|
| | from pyUltroid.fns.FastTelethon import upload_file |
| | from pyUltroid.fns.helper import progress |
| |
|
| | raw_file = None |
| | while not raw_file: |
| | with open(file, "rb") as f: |
| | raw_file = await upload_file( |
| | client=self, |
| | file=f, |
| | filename=filename, |
| | progress_callback=( |
| | lambda completed, total: self.loop.create_task( |
| | progress(completed, total, event, start_time, message) |
| | ) |
| | ) |
| | if show_progress |
| | else None, |
| | ) |
| | cache = { |
| | "by_bot": by_bot, |
| | "size": size, |
| | "path": path, |
| | "name": filename, |
| | "raw_file": raw_file, |
| | } |
| | if self._cache.get("upload_cache"): |
| | self._cache["upload_cache"].append(cache) |
| | else: |
| | self._cache.update({"upload_cache": [cache]}) |
| | if to_delete: |
| | with contextlib.suppress(FileNotFoundError): |
| | os.remove(file) |
| | return raw_file, time.time() - start_time |
| |
|
| | async def fast_downloader(self, file, **kwargs): |
| | """Download files in a faster way""" |
| | |
| | show_progress = kwargs.get("show_progress", False) |
| | filename = kwargs.get("filename", "") |
| | if show_progress: |
| | event = kwargs["event"] |
| | |
| | if file.size < 10 * 2 ** 20: |
| | show_progress = False |
| | import mimetypes |
| |
|
| | from telethon.tl.types import DocumentAttributeFilename |
| |
|
| | from pyUltroid.fns.FastTelethon import download_file |
| | from pyUltroid.fns.helper import progress |
| |
|
| | start_time = time.time() |
| | |
| | if not filename: |
| | try: |
| | if isinstance(file.attributes[-1], DocumentAttributeFilename): |
| | filename = file.attributes[-1].file_name |
| | except IndexError: |
| | mimetype = file.mime_type |
| | filename = ( |
| | mimetype.split("/")[0] |
| | + "-" |
| | + str(round(start_time)) |
| | + mimetypes.guess_extension(mimetype) |
| | ) |
| | message = kwargs.get("message", f"Downloading {filename}...") |
| |
|
| | raw_file = None |
| | while not raw_file: |
| | with open(filename, "wb") as f: |
| | raw_file = await download_file( |
| | client=self, |
| | location=file, |
| | out=f, |
| | progress_callback=( |
| | lambda completed, total: self.loop.create_task( |
| | progress(completed, total, event, start_time, message) |
| | ) |
| | ) |
| | if show_progress |
| | else None, |
| | ) |
| | return raw_file, time.time() - start_time |
| |
|
| | def run_in_loop(self, function): |
| | """run inside asyncio loop""" |
| | return self.loop.run_until_complete(function) |
| |
|
| | def run(self): |
| | """run asyncio loop""" |
| | self.run_until_disconnected() |
| |
|
| | def add_handler(self, func, *args, **kwargs): |
| | """Add new event handler, ignoring if exists""" |
| | if func in [_[0] for _ in self.list_event_handlers()]: |
| | return |
| | self.add_event_handler(func, *args, **kwargs) |
| |
|
| | @property |
| | def utils(self): |
| | return telethon_utils |
| |
|
| | @property |
| | def full_name(self): |
| | """full name of Client""" |
| | return self.utils.get_display_name(self.me) |
| |
|
| | @property |
| | def uid(self): |
| | """Client's user id""" |
| | return self.me.id |
| |
|
| | def to_dict(self): |
| | return dict(inspect.getmembers(self)) |
| |
|
| | async def parse_id(self, text): |
| | with contextlib.suppress(ValueError): |
| | text = int(text) |
| | return await self.get_peer_id(text) |
| |
|