WIP: Video support

This commit is contained in:
Profitroll 2023-06-22 15:17:44 +02:00
parent 070acb474d
commit f29c1e7ae6
Signed by: profitroll
GPG Key ID: FA35CAB49DACD3B2
6 changed files with 144 additions and 56 deletions

View File

@ -8,11 +8,13 @@ from shutil import rmtree
from time import time
from traceback import format_exc
from typing import List, Tuple, Union
import aiofiles
import pyrogram
from aiohttp import ClientSession
from bson import ObjectId
from dateutil.relativedelta import relativedelta
from classes.enums.submission_types import SubmissionType
from libbot import json_read, json_write
from libbot.i18n import BotLocale
from libbot.i18n.sync import _
@ -43,10 +45,14 @@ from classes.exceptions import (
)
from classes.pyrocommand import PyroCommand
from modules.api_client import (
BodyPhotoUploadAlbumsAlbumPhotosPost,
BodyPhotoUpload,
BodyVideoUpload,
File,
Photo,
Video,
client,
photo_upload,
video_upload,
)
from modules.database import col_submitted
from modules.http_client import http_session
@ -398,7 +404,7 @@ class PyroClient(Client):
language_code=command_set.language_code,
)
async def submit_photo(
async def submit_media(
self, id: str
) -> Tuple[Union[Message, None], Union[str, None]]:
db_entry = col_submitted.find_one({"_id": ObjectId(id)})
@ -431,24 +437,47 @@ class PyroClient(Client):
db_entry["user"], db_entry["telegram"]["msg_id"]
)
with open(str(filepath), "rb") as fh:
photo_bytes = BytesIO(fh.read())
async with aiofiles.open(str(filepath), "rb") as fh:
media_bytes = BytesIO(await fh.read())
try:
response = await photo_upload(
self.config["posting"]["api"]["album"],
client=client,
multipart_data=BodyPhotoUploadAlbumsAlbumPhotosPost(
File(photo_bytes, filepath.name, "image/jpeg")
),
ignore_duplicates=self.config["submission"]["allow_duplicates"],
compress=False,
caption="queue",
)
if db_entry["type"] == SubmissionType.PHOTO.value:
response = await photo_upload(
self.config["posting"]["api"]["album"],
client=client,
multipart_data=BodyPhotoUpload(
File(media_bytes, filepath.name, "image/jpeg")
),
ignore_duplicates=self.config["submission"]["allow_duplicates"],
compress=False,
caption="queue",
)
elif db_entry["type"] == SubmissionType.VIDEO.value:
response = await video_upload(
self.config["posting"]["api"]["album"],
client=client,
multipart_data=BodyVideoUpload(
File(media_bytes, filepath.name, "video/*")
),
caption="queue",
)
elif db_entry["type"] == SubmissionType.ANIMATION.value:
response = await video_upload(
self.config["posting"]["api"]["album"],
client=client,
multipart_data=BodyVideoUpload(
File(media_bytes, filepath.name, "video/*")
),
caption="queue",
)
except UnexpectedStatus:
raise SubmissionUnsupportedError(str(filepath))
response_dict = loads(response.content.decode("utf-8"))
response_dict = (
{}
if not hasattr(response, "content")
else loads(response.content.decode("utf-8"))
)
if "duplicates" in response_dict and len(response_dict["duplicates"]) > 0:
duplicates = []
@ -480,7 +509,10 @@ class PyroClient(Client):
except (FileNotFoundError, NotADirectoryError):
logger.error("Could not delete '%s' on submission accepted", filepath)
return submission, response.parsed.id
return (
submission,
response.id if not hasattr(response, "parsed") else response.parsed.id,
)
async def ban_user(self, id: int) -> None:
pass

View File

@ -56,6 +56,11 @@
"ignore_admins": true,
"text": "#submitted"
},
"types": {
"photo": true,
"video": false,
"animation": false
},
"extensions": {
"photo": [
"jpg",

View File

@ -35,14 +35,26 @@ from photosapi_client.api.default.user_me_users_me_get import sync as user_me
from photosapi_client.api.default.video_find_albums_album_videos_get import (
asyncio as video_find,
)
from photosapi_client.api.default.video_get_videos_id_get import asyncio as video_get
from photosapi_client.api.default.video_patch_videos_id_patch import (
asyncio as video_patch,
)
from photosapi_client.api.default.video_upload_albums_album_videos_post import (
asyncio as video_upload,
)
from photosapi_client.models.body_login_for_access_token_token_post import (
BodyLoginForAccessTokenTokenPost,
)
from photosapi_client.models.body_photo_upload_albums_album_photos_post import (
BodyPhotoUploadAlbumsAlbumPhotosPost,
BodyPhotoUploadAlbumsAlbumPhotosPost as BodyPhotoUpload,
)
from photosapi_client.models.body_video_upload_albums_album_videos_post import (
BodyVideoUploadAlbumsAlbumVideosPost as BodyVideoUpload,
)
from photosapi_client.models.http_validation_error import HTTPValidationError
from photosapi_client.models.photo import Photo
from photosapi_client.models.token import Token
from photosapi_client.models.video import Video
from photosapi_client.types import File
from modules.http_client import http_session

View File

@ -3,7 +3,7 @@ from datetime import datetime
from os import makedirs, path
from random import choice
from shutil import rmtree
from traceback import format_exc
from traceback import format_exc, print_exc
from uuid import uuid4
import aiofiles
@ -12,7 +12,16 @@ 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.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__)
@ -30,9 +39,19 @@ async def send_content(app: Client, http_session: ClientSession) -> None:
return
try:
pic = choice(
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 photo_find(
await func(
album=app.config["posting"]["api"]["album"],
caption="queue",
page_size=app.config["posting"]["page_size"],
@ -56,41 +75,48 @@ async def send_content(app: Client, http_session: ClientSession) -> None:
)
return
response = await http_session.get(
f"{app.config['posting']['api']['address']}/photos/{pic.id}",
headers={"Authorization": f"Bearer {token}"},
)
if response.status != 200:
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(
app._("post_invalid_pic", "console").format(
response.status, str(await response.json())
)
"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,
app._("post_invalid_pic", "message").format(
response.status, await response.json()
),
)
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, pic.filename)
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(await response.read())
await out_file.write(response.payload.read())
logger.info(
f"Candidate {pic.filename} ({pic.id}) is {path.getsize(path.join(app.config['locations']['tmp'], tmp_path))} bytes big",
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:
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)
@ -110,7 +136,9 @@ async def send_content(app: Client, http_session: ClientSession) -> None:
)
image.close()
if path.getsize(path.join(app.config["locations"]["tmp"], tmp_path)) > 5242880:
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
)
@ -118,7 +146,7 @@ async def send_content(app: Client, http_session: ClientSession) -> None:
del response
submitted = col_submitted.find_one({"temp.file": pic.filename})
submitted = col_submitted.find_one({"temp.file": media.filename})
if submitted is not None and submitted["caption"] is not None:
caption = submitted["caption"].strip()
@ -150,14 +178,24 @@ async def send_content(app: Client, http_session: ClientSession) -> None:
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"],
)
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 image {pic.filename} ({pic.id}) due to {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,
@ -169,8 +207,8 @@ async def send_content(app: Client, http_session: ClientSession) -> None:
col_sent.insert_one(
{
"date": datetime.now(),
"image": pic.id,
"filename": pic.filename,
"image": media.id,
"filename": media.filename,
"channel": app.config["posting"]["channel"],
"caption": None
if (submitted is None or submitted["caption"] is None)
@ -178,13 +216,14 @@ async def send_content(app: Client, http_session: ClientSession) -> None:
}
)
await photo_patch(id=pic.id, client=client, caption="sent")
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(
pic.id,
media.id,
str(app.config["posting"]["channel"]),
caption.replace("\n", "%n"),
str(app.config["posting"]["silent"]),

View File

@ -18,7 +18,7 @@ from ujson import loads
from classes.pyroclient import PyroClient
from modules.api_client import (
BodyPhotoUploadAlbumsAlbumPhotosPost,
BodyPhotoUpload,
File,
client,
photo_delete,
@ -158,7 +158,7 @@ async def cmd_import(app: PyroClient, msg: Message):
uploaded = await photo_upload(
app.config["posting"]["api"]["album"],
client=client,
multipart_data=BodyPhotoUploadAlbumsAlbumPhotosPost(
multipart_data=BodyPhotoUpload(
File(photo_bytes, Path(filename).name, "image/jpeg")
),
ignore_duplicates=app.config["submission"]["allow_duplicates"],

View File

@ -215,7 +215,7 @@ async def get_submission(app: PyroClient, msg: Message):
and app.config["submission"]["require_confirmation"]["admins"] is False
):
try:
submitted = await app.submit_photo(str(inserted.inserted_id))
submitted = await app.submit_media(str(inserted.inserted_id))
await msg.reply_text(
app._("sub_yes_auto", "message", locale=user_locale),
disable_notification=True,