import logging from datetime import datetime from os import makedirs, path from random import choice from shutil import rmtree from traceback import format_exc from uuid import uuid4 import aiofiles from aiohttp import ClientSession from photosapi_client.errors import UnexpectedStatus from PIL import Image from pyrogram.client import Client from modules.api_client import authorize, client, photo_find, photo_patch from modules.database import col_sent, col_submitted logger = logging.getLogger(__name__) async def send_content(app: Client, http_session: ClientSession) -> None: try: try: token = await authorize(http_session) except ValueError: await app.send_message( app.owner, app._("api_creds_invalid", "message"), ) return try: pic = choice( ( await photo_find( album=app.config["posting"]["api"]["album"], caption="queue", page_size=app.config["posting"]["page_size"], client=client, ) ).results ) except (KeyError, AttributeError, TypeError, IndexError): logger.info(app._("post_empty", "console")) if app.config["reports"]["error"]: await app.send_message( app.owner, app._("api_queue_empty", "message"), ) return except (ValueError, UnexpectedStatus): if app.config["reports"]["error"]: await app.send_message( app.owner, app._("api_queue_error", "message"), ) return response = await http_session.get( f"{app.config['posting']['api']['address']}/photos/{pic.id}", headers={"Authorization": f"Bearer {token}"}, ) if response.status != 200: logger.warning( app._("post_invalid_pic", "console").format( response.status, str(await response.json()) ) ) if app.config["reports"]["error"]: await app.send_message( app.owner, app._("post_invalid_pic", "message").format( response.status, await response.json() ), ) tmp_dir = str(uuid4()) makedirs(path.join(app.config["locations"]["tmp"], tmp_dir), exist_ok=True) tmp_path = path.join(tmp_dir, pic.filename) async with aiofiles.open( path.join(app.config["locations"]["tmp"], tmp_path), "wb" ) as out_file: await out_file.write(await response.read()) logger.info( f"Candidate {pic.filename} ({pic.id}) is {path.getsize(path.join(app.config['locations']['tmp'], tmp_path))} bytes big", ) if path.getsize(path.join(app.config["locations"]["tmp"], tmp_path)) > 5242880: image = Image.open(path.join(app.config["locations"]["tmp"], tmp_path)) width, height = image.size image = image.resize((int(width / 2), int(height / 2)), Image.ANTIALIAS) if tmp_path.lower().endswith(".jpeg") or tmp_path.lower().endswith(".jpg"): image.save( path.join(app.config["locations"]["tmp"], tmp_path), "JPEG", optimize=True, quality=50, ) elif tmp_path.lower().endswith(".png"): image.save( path.join(app.config["locations"]["tmp"], tmp_path), "PNG", optimize=True, compress_level=8, ) image.close() if path.getsize(path.join(app.config["locations"]["tmp"], tmp_path)) > 5242880: rmtree( path.join(app.config["locations"]["tmp"], tmp_dir), ignore_errors=True ) raise BytesWarning del response submitted = col_submitted.find_one({"temp.file": pic.filename}) if submitted is not None and submitted["caption"] is not None: caption = submitted["caption"].strip() else: caption = "" if ( submitted is not None and app.config["posting"]["submitted_caption"]["enabled"] and ( (submitted["user"] not in app.admins) or ( app.config["posting"]["submitted_caption"]["ignore_admins"] is False ) ) ): caption = ( f"{caption}\n\n{app.config['posting']['submitted_caption']['text']}\n" ) else: caption = f"{caption}\n\n" if app.config["caption"]["enabled"]: if app.config["caption"]["link"] is not None: caption = f"{caption}[{choice(app.config['caption']['text'])}]({app.config['caption']['link']})" else: caption = f"{caption}{choice(app.config['caption']['text'])}" else: caption = caption try: sent = await app.send_photo( app.config["posting"]["channel"], path.join(app.config["locations"]["tmp"], tmp_path), caption=caption, disable_notification=app.config["posting"]["silent"], ) except Exception as exp: logger.error(f"Could not send image {pic.filename} ({pic.id}) due to {exp}") if app.config["reports"]["error"]: await app.send_message( app.owner, app._("post_exception", "message").format(exp, format_exc()), ) # rmtree(path.join(app.config['locations']['tmp'], tmp_dir), ignore_errors=True) return col_sent.insert_one( { "date": datetime.now(), "image": pic.id, "filename": pic.filename, "channel": app.config["posting"]["channel"], "caption": None if (submitted is None or submitted["caption"] is None) else submitted["caption"].strip(), } ) await photo_patch(id=pic.id, client=client, caption="sent") rmtree(path.join(app.config["locations"]["tmp"], tmp_dir), ignore_errors=True) logger.info( app._("post_sent", "console").format( pic.id, str(app.config["posting"]["channel"]), caption.replace("\n", "%n"), str(app.config["posting"]["silent"]), ) ) except Exception as exp: logger.error(app._("post_exception", "console").format(str(exp), format_exc())) if app.config["reports"]["error"]: await app.send_message( app.owner, app._("post_exception", "message").format(exp, format_exc()), ) try: rmtree( path.join(app.config["locations"]["tmp"], tmp_dir), ignore_errors=True ) except: pass