This repository has been archived on 2024-08-21. You can view files and clone it, but cannot push or open issues or pull requests.
TelegramPoster/modules/sender.py
2023-06-22 15:17:44 +02:00

246 lines
8.4 KiB
Python

import logging
from datetime import datetime
from os import makedirs, path
from random import choice
from shutil import rmtree
from traceback import format_exc, print_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_get,
photo_patch,
video_find,
video_get,
video_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:
funcs = []
if app.config["posting"]["types"]["photo"]:
funcs.append(photo_find)
if (
app.config["posting"]["types"]["video"]
or app.config["posting"]["types"]["animation"]
):
funcs.append(video_find)
func = choice(funcs)
media = choice(
(
await func(
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
try:
if func is photo_find:
response = await photo_get(id=media.id, client=client)
else:
response = await video_get(id=media.id, client=client)
except Exception as exp:
print_exc()
logger.warning(
"Media is invalid: %s",
exp
# app._("post_invalid_pic", "console").format(
# response.status, str(await response.json())
# )
)
if app.config["reports"]["error"]:
await app.send_message(app.owner, f"Media is invalid: {exp}")
return
# 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, media.filename)
async with aiofiles.open(
path.join(app.config["locations"]["tmp"], tmp_path), "wb"
) as out_file:
await out_file.write(response.payload.read())
logger.info(
f"Candidate {media.filename} ({media.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
) and func is photo_find:
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
) and func is photo_find:
rmtree(
path.join(app.config["locations"]["tmp"], tmp_dir), ignore_errors=True
)
raise BytesWarning
del response
submitted = col_submitted.find_one({"temp.file": media.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:
if func is photo_find:
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"],
)
else:
sent = await app.send_video(
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 media {media.filename} ({media.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": media.id,
"filename": media.filename,
"channel": app.config["posting"]["channel"],
"caption": None
if (submitted is None or submitted["caption"] is None)
else submitted["caption"].strip(),
}
)
func_patch = photo_patch if func is photo_find else video_patch
await func_patch(id=media.id, client=client, caption="sent")
rmtree(path.join(app.config["locations"]["tmp"], tmp_dir), ignore_errors=True)
logger.info(
app._("post_sent", "console").format(
media.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