TelegramPoster/modules/sender.py

271 lines
9.1 KiB
Python
Raw Normal View History

import logging
2023-02-17 22:55:38 +02:00
from datetime import datetime
2023-02-14 17:25:56 +02:00
from os import makedirs, path
from random import choice, sample
2023-03-02 23:38:48 +02:00
from shutil import rmtree
from traceback import format_exc, print_exc
from typing import Union
2023-02-14 17:25:56 +02:00
from uuid import uuid4
import aiofiles
from aiohttp import ClientSession
from libbot.pyrogram.classes import PyroClient
from photosapi_client.errors import UnexpectedStatus
from PIL import Image
2023-02-14 17:25:56 +02:00
from modules.api_client import (
File,
PhotoSearch,
VideoSearch,
authorize,
client,
photo_get,
photo_patch,
photo_random,
video_get,
video_patch,
video_random,
)
2023-02-14 17:25:56 +02:00
from modules.database import col_sent, col_submitted
logger = logging.getLogger(__name__)
2023-01-10 13:52:44 +02:00
async def send_content(app: PyroClient, http_session: ClientSession) -> None:
2023-01-10 13:52:44 +02:00
try:
2023-02-14 17:25:56 +02:00
try:
token = await authorize(http_session)
2023-02-14 17:25:56 +02:00
except ValueError:
2023-03-09 12:33:02 +02:00
await app.send_message(
app.owner,
app._("api_creds_invalid", "message"),
2023-03-09 12:33:02 +02:00
)
2023-02-14 17:25:56 +02:00
return
2023-01-17 15:11:23 +02:00
2023-02-14 17:25:56 +02:00
try:
funcs = []
if app.config["posting"]["types"]["photo"]:
funcs.append((photo_random, photo_get, app.send_photo, photo_patch))
if app.config["posting"]["types"]["video"]:
funcs.append((video_random, video_get, app.send_video, video_patch))
if not funcs:
raise KeyError(
"No media source provided: all seem to be disabled in config"
2023-03-09 12:33:02 +02:00
)
if len(funcs) > 1:
found = False
for func_iter in sample(funcs, len(funcs)):
func = func_iter
random_results = (
await func_iter[0](
album=app.config["posting"]["api"]["album"],
caption="queue",
client=client,
limit=1,
)
).results
if not random_results:
continue
media: Union[PhotoSearch, VideoSearch] = random_results[0]
try:
response: File = await func_iter[1](id=media.id, client=client)
except Exception as exp:
print_exc()
logger.error("Media is invalid: %s", exp)
if app.config["reports"]["error"]:
await app.send_message(
app.owner, f"Media is invalid: {exp}"
)
return
found = True
break
if not found:
raise KeyError("No media found")
else:
func = funcs[0]
media: Union[PhotoSearch, VideoSearch] = (
await func[0](
album=app.config["posting"]["api"]["album"],
caption="queue",
client=client,
limit=1,
)
).results[0]
try:
response: File = await func[1](id=media.id, client=client)
except Exception as exp:
print_exc()
logger.error("Media is invalid: %s", exp)
if app.config["reports"]["error"]:
await app.send_message(app.owner, f"Media is invalid: {exp}")
return
except (KeyError, AttributeError, TypeError, IndexError):
2023-07-03 12:42:28 +03:00
logger.info(
"Could not send content due to queue empty or contains only forbidden extensions"
)
if app.config["reports"]["error"]:
2023-03-09 12:33:02 +02:00
await app.send_message(
app.owner,
app._("api_queue_empty", "message"),
2023-03-09 12:33:02 +02:00
)
2023-02-14 17:25:56 +02:00
return
2023-03-09 12:33:02 +02:00
except (ValueError, UnexpectedStatus):
if app.config["reports"]["error"]:
2023-03-09 12:33:02 +02:00
await app.send_message(
app.owner,
app._("api_queue_error", "message"),
2023-03-09 12:33:02 +02:00
)
return
2023-01-17 15:11:23 +02:00
2023-02-14 17:25:56 +02:00
tmp_dir = str(uuid4())
2023-01-17 15:11:23 +02:00
makedirs(path.join(app.config["locations"]["tmp"], tmp_dir), exist_ok=True)
2023-01-17 15:11:23 +02:00
tmp_path = path.join(tmp_dir, media.filename)
2023-01-17 15:11:23 +02:00
2023-03-09 12:33:02 +02:00
async with aiofiles.open(
path.join(app.config["locations"]["tmp"], tmp_path), "wb"
2023-03-09 12:33:02 +02:00
) as out_file:
await out_file.write(response.payload.read())
2023-01-17 15:11:23 +02:00
logger.info(
"Candidate %s (%s) is %s bytes big",
media.filename,
media.id,
path.getsize(path.join(app.config["locations"]["tmp"], tmp_path)),
2023-03-09 12:33:02 +02:00
)
2023-02-17 17:46:44 +02:00
if (
path.getsize(path.join(app.config["locations"]["tmp"], tmp_path)) > 5242880
) and func[0] is photo_random:
image = Image.open(path.join(app.config["locations"]["tmp"], tmp_path))
2023-02-17 17:46:44 +02:00
width, height = image.size
2023-03-09 12:33:02 +02:00
image = image.resize((int(width / 2), int(height / 2)), Image.ANTIALIAS)
2023-02-17 17:46:44 +02:00
if tmp_path.lower().endswith(".jpeg") or tmp_path.lower().endswith(".jpg"):
2023-03-09 12:33:02 +02:00
image.save(
path.join(app.config["locations"]["tmp"], tmp_path),
2023-03-09 12:33:02 +02:00
"JPEG",
optimize=True,
quality=50,
)
2023-02-17 17:46:44 +02:00
elif tmp_path.lower().endswith(".png"):
2023-03-09 12:33:02 +02:00
image.save(
path.join(app.config["locations"]["tmp"], tmp_path),
2023-03-09 12:33:02 +02:00
"PNG",
optimize=True,
compress_level=8,
)
2023-02-17 17:46:44 +02:00
image.close()
2023-03-09 12:33:02 +02:00
if (
path.getsize(path.join(app.config["locations"]["tmp"], tmp_path)) > 5242880
) and func[0] is photo_random:
2023-03-09 12:33:02 +02:00
rmtree(
path.join(app.config["locations"]["tmp"], tmp_dir), ignore_errors=True
2023-03-09 12:33:02 +02:00
)
2023-02-17 17:46:44 +02:00
raise BytesWarning
2023-02-14 17:25:56 +02:00
del response
2023-01-10 13:52:44 +02:00
submitted = col_submitted.find_one({"temp.file": media.filename})
2023-01-10 13:52:44 +02:00
2023-02-18 00:18:34 +02:00
if submitted is not None and submitted["caption"] is not None:
caption = submitted["caption"].strip()
2023-01-10 13:52:44 +02:00
else:
caption = ""
2023-03-09 12:33:02 +02:00
if (
submitted is not None
and app.config["posting"]["submitted_caption"]["enabled"]
2023-03-09 12:33:02 +02:00
and (
(submitted["user"] not in app.admins)
or (
app.config["posting"]["submitted_caption"]["ignore_admins"] is False
)
2023-03-09 12:33:02 +02:00
)
2023-02-24 20:48:06 +02:00
):
2023-03-09 12:33:02 +02:00
caption = (
f"{caption}\n\n{app.config['posting']['submitted_caption']['text']}\n"
2023-03-09 12:33:02 +02:00
)
2023-02-24 19:39:33 +02:00
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']})"
2023-01-10 13:52:44 +02:00
else:
caption = f"{caption}{choice(app.config['caption']['text'])}"
2023-01-10 13:52:44 +02:00
else:
caption = caption
2023-02-14 17:25:56 +02:00
try:
sent = await func[2](
app.config["posting"]["channel"],
path.join(app.config["locations"]["tmp"], tmp_path),
2023-03-09 12:33:02 +02:00
caption=caption,
disable_notification=app.config["posting"]["silent"],
2023-03-09 12:33:02 +02:00
)
2023-02-14 17:25:56 +02:00
except Exception as exp:
logger.error(
"Could not send media %s (%s) due to %s", media.filename, media.id, exp
)
if app.config["reports"]["error"]:
2023-03-09 12:33:02 +02:00
await app.send_message(
app.owner,
app._("post_exception", "message").format(exp, format_exc()),
2023-03-09 12:33:02 +02:00
)
# rmtree(path.join(app.config['locations']['tmp'], tmp_dir), ignore_errors=True)
2023-02-14 17:25:56 +02:00
return
2023-01-10 13:52:44 +02:00
2023-02-14 17:25:56 +02:00
col_sent.insert_one(
{
2023-02-17 22:55:38 +02:00
"date": datetime.now(),
"image": media.id,
"filename": media.filename,
"channel": app.config["posting"]["channel"],
2023-03-09 12:33:02 +02:00
"caption": None
if (submitted is None or submitted["caption"] is None)
else submitted["caption"].strip(),
2023-02-14 17:25:56 +02:00
}
)
2023-01-10 13:52:44 +02:00
await func[3](id=media.id, client=client, caption="sent")
2023-01-10 13:52:44 +02:00
rmtree(path.join(app.config["locations"]["tmp"], tmp_dir), ignore_errors=True)
2023-01-10 13:52:44 +02:00
logger.info(
2023-07-03 12:42:28 +03:00
"Sent %s to %s with caption %s and silently %s",
media.id,
str(app.config["posting"]["channel"]),
caption.replace("\n", "%n"),
str(app.config["posting"]["silent"]),
2023-03-09 12:33:02 +02:00
)
2023-01-10 13:52:44 +02:00
2023-02-14 17:25:56 +02:00
except Exception as exp:
2023-07-03 12:42:28 +03:00
logger.error(
"Could not send content due to %s. Traceback: %s", exp, format_exc()
)
if app.config["reports"]["error"]:
2023-03-09 12:33:02 +02:00
await app.send_message(
app.owner,
app._("post_exception", "message").format(exp, format_exc()),
2023-03-09 12:33:02 +02:00
)
2023-02-17 17:46:44 +02:00
try:
2023-03-09 12:33:02 +02:00
rmtree(
path.join(app.config["locations"]["tmp"], tmp_dir), ignore_errors=True
2023-03-09 12:33:02 +02:00
)
2023-02-17 17:46:44 +02:00
except:
2023-03-09 12:33:02 +02:00
pass