import asyncio import random from io import BytesIO import aiohttp # noinspection PyUnresolvedReferences from modules.squotes import render_message from pyrogram import Client, enums, filters, types from pyrogram.types import Message # noinspection PyUnresolvedReferences from utils.misc import modules_help, prefix from utils.scripts import format_exc, import_library, resize_image Image = import_library("PIL", "pillow").Image np = import_library("numpy") imageio = import_library("imageio") def create_gif(filename: str, offset: int, fps: int = 2, typ: str = "spin"): img = Image.open(f"downloads/{filename}") if typ.lower() != "spin": img = img.resize( (random.randint(200, 1280), random.randint(200, 1280)), Image.ANTIALIAS ) imageio.mimsave( "downloads/video.gif", [img.rotate(-(i % 360)) for i in range(1, 361, offset)], fps=fps, ) async def quote_cmd(client: Client, message: types.Message): count = 1 is_png = False send_for_me = False no_reply = False messages = [] async for msg in client.get_chat_history( message.chat.id, offset_id=message.reply_to_message.id, reverse=True ): if msg.empty: continue if msg.message_id >= message.id: break if no_reply: msg.reply_to_message = None messages.append(msg) if len(messages) >= count: break if send_for_me: await message.delete() message = await client.send_message( "me", "Generating...", parse_mode=enums.ParseMode.HTML ) else: await message.edit("Generating...", parse_mode=enums.ParseMode.HTML) url = "https://quotes.fl1yd.su/generate" params = { "messages": [ await render_message(client, msg) for msg in messages if not msg.empty ], "quote_color": "#162330", "text_color": "#fff", } response = await aiohttp.ClientSession().post(url, json=params) if response.status != 200: return await message.edit( f"Quotes API error!\n" f"{response.text}", parse_mode=enums.ParseMode.HTML, ) resized = resize_image( BytesIO(await response.read()), img_type="PNG" if is_png else "WEBP" ) return resized, is_png @Client.on_message(filters.command(["spin", "dspin"], prefix) & filters.me) async def spin_handler(client: Client, message: Message): if not message.reply_to_message: await message.edit( "Reply to a message to spin it!", parse_mode=enums.ParseMode.HTML, ) await message.edit( "Downloading sticker...", parse_mode=enums.ParseMode.HTML ) return await message.edit( "Invalid file type!", parse_mode=enums.ParseMode.HTML ) try: coro = True if message.reply_to_message.document: filename = message.reply_to_message.document.file_name if ( not filename.endswith(".webp") and not filename.endswith(".png") and not filename.endswith(".jpg") and not filename.endswith(".jpeg") ): return await message.edit( "Invalid file type!", parse_mode=enums.ParseMode.HTML ) elif message.reply_to_message.sticker: if message.reply_to_message.sticker.is_video: return await message.edit( "Video stickers not allowed", parse_mode=enums.ParseMode.HTML ) filename = "sticker.webp" elif message.reply_to_message.text: result = await quote_cmd(client, message) if result[1]: filename = "sticker.png" else: filename = "sticker.webp" open(f"downloads/" + filename, "wb").write(result[0].getbuffer()) coro = False else: filename = "photo.jpg" if coro: await message.reply_to_message.download(f"downloads/{filename}") except Exception as ex: return await message.edit( f"Message can not be loaded:\n{format_exc(ex)}", parse_mode=enums.ParseMode.HTML, ) await message.edit("Spinning...", parse_mode=enums.ParseMode.HTML) offset = int(message.command[1]) if len(message.command) > 1 else 10 fps = int(message.command[2]) if len(message.command) > 2 else 30 try: loop = asyncio.get_event_loop() await loop.run_in_executor( None, lambda: create_gif(filename, offset, fps, message.command[0]) ) await message.delete() return await client.send_animation( chat_id=message.chat.id, animation="downloads/video.gif", reply_to_message_id=message.reply_to_message.id, ) except Exception as e: await message.reply(format_exc(e), parse_mode=enums.ParseMode.HTML) modules_help["spin"] = { "spin [offset] [fps]": "Spin message (Reply required)", "dspin [offset] [fps]": "SHAKAL spin message (Reply required)", }