From 435589ec98546db4845a21be343a01c63eefedde Mon Sep 17 00:00:00 2001 From: Sergey Elpashev Date: Mon, 28 Jul 2025 18:16:04 +0300 Subject: [PATCH] Final version --- .gitignore | 4 +- controllers.py | 196 +++++++++++++++++++++++++++++++++++++++++++++++ helpers.py | 42 ++++++++++ main.py | 19 +++-- progress.py | 90 ++++++++++++++++++++++ requirements.txt | 4 + 6 files changed, 348 insertions(+), 7 deletions(-) create mode 100644 helpers.py create mode 100644 progress.py create mode 100644 requirements.txt diff --git a/.gitignore b/.gitignore index c61028f..001f703 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ .env *.session __pycache__/ -venv/ \ No newline at end of file +venv/ +downloads/ +*.session-journal \ No newline at end of file diff --git a/controllers.py b/controllers.py index e69de29..06ba6cd 100644 --- a/controllers.py +++ b/controllers.py @@ -0,0 +1,196 @@ +import asyncio +import os +import random +import shutil +import time +from asyncio import AbstractEventLoop +from time import sleep + +from ethon.pyfunc import video_metadata +from pyrogram import Client, filters +from pyrogram.errors import FloodWait +from pyrogram.methods.utilities import idle +from pyrogram.raw.functions.channels import GetMessages +from pyrogram.types import Chat, Message + +from config import APP_HASH, APP_ID +from helpers import screenshot +from progress import progress_for_pyrogram + + +class Telegram: + def __init__(self, loop): + self.client = None + + self.event_loop: AbstractEventLoop = loop + # self.autodeleting = None + + def thumbnail(sender): + if os.path.exists(f"{sender}.jpg"): + return f'{sender}.jpg' + return None + + async def create_session(self): + instance = self + self.client = Client("my_account", APP_ID, APP_HASH) + + @self.client.on_message(filters.command("echo", prefixes=".") & filters.private) + async def echo(self: Client, message: Message): + while 1: + try: + await message.reply(message.text.split('.echo ', maxsplit=1)[1]) + return + except FloodWait as e: + await asyncio.sleep(e.x) + + @self.client.on_message(filters.command("type", prefixes=".") & filters.private) + async def hello(self: Client, message: Message): + msg = await self.send_message(message.chat.id, message.text.split('.type ', maxsplit=1)[1]) + + orig_text = message.text.split(".type ", maxsplit=1)[1] + text = orig_text + tbp = "" + typing_symbol = "█" + + while tbp != orig_text: + try: + await msg.edit(tbp+typing_symbol) + sleep(0.05) + + tbp += text[0] + text = text[1:] + + await msg.edit(tbp) + sleep(0.05) + except FloodWait as e: + sleep(e.x) + + @self.client.on_message(filters.command("test", prefixes=".") & filters.me) + async def test(self: Client, msg: Message): + edit_msg = await msg.reply("Processing!") + msg_text = msg.text.split(".test ", maxsplit=1)[1] + msg_id = int(msg_text.split("/")[-1]) + if 't.me/c/' in msg_text: + try: + chat = int('-100'+str(msg_text.split("/")[-2])) + mes = await self.get_messages(chat, msg_id) + print("Rabotaet") + edit = await self.edit_message_text(msg.chat.id, edit_msg.id, "Trying to download!") + file = await self.download_media( + mes, + progress=progress_for_pyrogram, + progress_args=( + self, + "**DOWNLOADING:**\n", + edit, + time.time() + ) + ) + caption = mes.caption + # await self.send_message("me", mes.caption,entities=mes.caption_entities,disable_web_page_preview=True) + # await self.send_photo("me", file, caption=mes.caption) + await edit.edit('Preparing to upload!') + if str(file).split(".")[-1] in ['mkv', 'mp4', 'webm']: + if str(file).split(".")[-1] in ['webm', 'mkv']: + path = str(file).split(".")[0] + ".mp4" + os.rename(file, path) + file = str(file).split(".")[0] + ".mp4" + data = video_metadata(file) + duration = data['duration'] + thumb_path = await screenshot(file, duration, msg.from_user.id) + await self.send_video( + msg.chat.id, + video=file, + caption=caption, + thumb=thumb_path, + duration=duration, + caption_entities=mes.caption_entities, + progress=progress_for_pyrogram, + has_spoiler=True, + progress_args=( + self, + "**UPLOADING:**\n", + edit, + time.time() + ) + ) + elif str(file).split(".")[-1] in ['png', 'jpeg', 'jpg', 'webp']: + await self.send_photo(msg.chat.id, photo=file, caption=caption, caption_entities=mes.caption_entities) + await edit.delete() + if os.path.exists(str(file)): + os.remove(str(file)) + except ValueError: + print("Plohaya ssylka") + except Exception as e: + print(e) + print("Tebya net v kanale, loh") + else: + chat = str(msg_text.split("/")[-2]) + edit = await self.edit_message_text(msg.chat.id, edit_msg.id, "Cloning...") + try: + await self.copy_message(msg.chat.id, chat, msg_id) + except Exception as e: + print(e) + return await self.edit_message_text(msg.chat.id, edit_msg.id, f"Failed to clone: {msg_text}") + await edit_msg.delete() + + @self.client.on_message(filters.command("hack", prefixes=".") & filters.me) + def hack(_, msg): + perc = 0 + + while (perc < 100): + try: + text = "👮‍ Взлом пентагона в процессе ..." + \ + str(perc) + "%" + msg.edit(text) + + perc += random.randint(1, 3) + sleep(0.1) + + except FloodWait as e: + sleep(e.x) + + msg.edit("🟢 Пентагон успешно взломан!") + sleep(3) + + msg.edit("👽 Поиск секретных данных об НЛО ...") + perc = 0 + + while (perc < 100): + try: + text = "👽 Поиск секретных данных об НЛО ..." + \ + str(perc) + "%" + msg.edit(text) + + perc += random.randint(1, 5) + sleep(0.15) + + except FloodWait as e: + sleep(e.x) + + msg.edit("🦖 Найдены данные о существовании динозавров на земле!") + + @self.client.on_disconnect() + async def disconnect_handler(self, message=None): + while not self.is_connected: + await asyncio.sleep(10) + + if self.is_connected: + print("Connected again!") + break + try: + await self.connect() + except: + pass + + def start_session(self): + if self.client: + # print("Bot Started!") + self.client.run() + print("Bot shutdown!") + if os.path.exists("./downloads"): + shutil.rmtree("./downloads") + if os.path.exists("./downloads"): + shutil.rmtree("./downloads") + if os.path.exists("./downloads"): + shutil.rmtree("./downloads") diff --git a/helpers.py b/helpers.py new file mode 100644 index 0000000..f46cd6d --- /dev/null +++ b/helpers.py @@ -0,0 +1,42 @@ +import asyncio +import os +import time +from datetime import datetime + + +def hhmmss(seconds): + x = time.strftime('%H:%M:%S', time.gmtime(seconds)) + return x + + +async def screenshot(video, duration, sender): + if os.path.exists(f'{sender}.jpg'): + return f'{sender}.jpg' + time_stamp = hhmmss(int(duration)/2) + out = datetime.now().isoformat("-", "seconds")+".jpg" + cmd = ["ffmpeg", + "-ss", + f"{time_stamp}", + "-i", + f"{video}" + "-frames:v", + "1", + f"{out}" + "-y" + ] + process = await asyncio.create_subprocess_exec( + *cmd, + stdout=asyncio.subprocess.PIPE, + stderr=asyncio.subprocess.PIPE + ) + stdout, stderr = await process.communicate() + x = stderr.decode().strip() + y = stdout.decode().strip() + if os.path.isfile(out): + return out + else: + None + if os.path.isfile(out): + return out + else: + None diff --git a/main.py b/main.py index b6447b1..8f2e38e 100644 --- a/main.py +++ b/main.py @@ -1,12 +1,19 @@ import asyncio -from pyrogram import Client +import uvloop -from config import APP_HASH, APP_ID +from controllers import Telegram -async def main(): - async with Client("my_account", APP_ID, APP_HASH) as app: - await app.send_message("me", "Hello, world2!") +def main(): + loop = asyncio.get_event_loop() + telegram = Telegram(loop=loop) + futures = [ + asyncio.ensure_future(telegram.create_session()), + ] + loop.run_until_complete(asyncio.gather(*futures)) + telegram.start_session() -asyncio.run(main()) + +if __name__ == "__main__": + main() diff --git a/progress.py b/progress.py new file mode 100644 index 0000000..a2c8379 --- /dev/null +++ b/progress.py @@ -0,0 +1,90 @@ +import json +import math +import os +import time + +FINISHED_PROGRESS_STR = "█" +UN_FINISHED_PROGRESS_STR = "" +DOWNLOAD_LOCATION = "/app" + + +async def progress_for_pyrogram( + current, + total, + bot, + ud_type, + message, + start +): + now = time.time() + diff = now - start + if round(diff % 10.00) == 0 or current == total: + percentage = current * 100 / total + status = DOWNLOAD_LOCATION + "/status.json" + if os.path.exists(status): + with open(status, 'r+') as f: + statusMsg = json.load(f) + if not statusMsg["running"]: + bot.stop_transmission() + speed = current / diff + elapsed_time = round(diff) * 1000 + time_to_completion = round((total - current) / speed) * 1000 + estimated_total_time = elapsed_time + time_to_completion + + elapsed_time = TimeFormatter(milliseconds=elapsed_time) + estimated_total_time = TimeFormatter(milliseconds=estimated_total_time) + + progress = "**[{0}{1}]** `| {2}%`\n\n".format( + ''.join([FINISHED_PROGRESS_STR for i in range( + math.floor(percentage / 10))]), + ''.join([UN_FINISHED_PROGRESS_STR for i in range( + 10 - math.floor(percentage / 10))]), + round(percentage, 2)) + + tmp = progress + "GROSSS: {0} of {1}\n\nSpeed: {2}/s\n\nETA: {3}\n".format( + humanbytes(current), + humanbytes(total), + humanbytes(speed), + estimated_total_time if estimated_total_time != '' else "0 s" + ) + try: + if not message.photo: + await message.edit_text( + text="{}\n {}".format( + ud_type, + tmp + ) + ) + else: + await message.edit_caption( + caption="{}\n {}".format( + ud_type, + tmp + ) + ) + except: + pass + + +def humanbytes(size): + if not size: + return "" + power = 2**10 + n = 0 + Dic_powerN = {0: ' ', 1: 'Ki', 2: 'Mi', 3: 'Gi', 4: 'Ti'} + while size > power: + size /= power + n += 1 + return str(round(size, 2)) + " " + Dic_powerN[n] + 'B' + + +def TimeFormatter(milliseconds: int) -> str: + seconds, milliseconds = divmod(int(milliseconds), 1000) + minutes, seconds = divmod(seconds, 60) + hours, minutes = divmod(minutes, 60) + days, hours = divmod(hours, 24) + tmp = ((str(days) + "d, ") if days else "") + \ + ((str(hours) + "h, ") if hours else "") + \ + ((str(minutes) + "m, ") if minutes else "") + \ + ((str(seconds) + "s, ") if seconds else "") + return tmp[:-2] diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..4a2d3ef --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +ethon==0.1.5 +Pyrogram==2.0.106 +python-dotenv==1.1.1 +uvloop==0.21.0