Compare commits

...

4 Commits

Author SHA1 Message Date
e2a73d5c4d Bug fixes and improvements 2023-06-27 23:40:36 +02:00
66d9956026 Photo and Video support 2023-06-27 23:05:37 +02:00
f0cad86dd6 Temp: Removed animation support 2023-06-27 20:04:03 +02:00
39b9c365fb Added support for random media 2023-06-27 20:03:14 +02:00
6 changed files with 126 additions and 100 deletions

View File

@@ -4,5 +4,5 @@ from enum import Enum
class SubmissionType(Enum): class SubmissionType(Enum):
DOCUMENT = "document" DOCUMENT = "document"
VIDEO = "video" VIDEO = "video"
ANIMATION = "animation" # ANIMATION = "animation"
PHOTO = "photo" PHOTO = "photo"

View File

@@ -199,15 +199,15 @@ class PyroClient(PyroClient):
), ),
caption="queue", caption="queue",
) )
elif db_entry["type"] == SubmissionType.ANIMATION.value: # elif db_entry["type"] == SubmissionType.ANIMATION.value:
response = await video_upload( # response = await video_upload(
self.config["posting"]["api"]["album"], # self.config["posting"]["api"]["album"],
client=client, # client=client,
multipart_data=BodyVideoUpload( # multipart_data=BodyVideoUpload(
File(media_bytes, filepath.name, "video/*") # File(media_bytes, filepath.name, "video/*")
), # ),
caption="queue", # caption="queue",
) # )
except UnexpectedStatus as exp: except UnexpectedStatus as exp:
raise SubmissionUnsupportedError(str(filepath)) from exp raise SubmissionUnsupportedError(str(filepath)) from exp

View File

@@ -51,7 +51,6 @@
"move_sent": false, "move_sent": false,
"use_interval": false, "use_interval": false,
"interval": "1h30m", "interval": "1h30m",
"page_size": 300,
"submitted_caption": { "submitted_caption": {
"enabled": true, "enabled": true,
"ignore_admins": true, "ignore_admins": true,
@@ -59,14 +58,12 @@
}, },
"types": { "types": {
"photo": true, "photo": true,
"video": false, "video": false
"animation": false
}, },
"extensions": { "extensions": {
"photo": [ "photo": [
"jpg", "jpg",
"png", "png",
"gif",
"jpeg" "jpeg"
], ],
"video": [ "video": [
@@ -114,7 +111,6 @@
}, },
"mime_types": [ "mime_types": [
"image/png", "image/png",
"image/gif",
"image/jpeg", "image/jpeg",
"video/mp4", "video/mp4",
"video/quicktime" "video/quicktime"

View File

@@ -27,6 +27,9 @@ from photosapi_client.api.default.photo_get_photos_id_get import asyncio as phot
from photosapi_client.api.default.photo_patch_photos_id_patch import ( from photosapi_client.api.default.photo_patch_photos_id_patch import (
asyncio as photo_patch, asyncio as photo_patch,
) )
from photosapi_client.api.default.photo_random_albums_album_photos_random_get import (
asyncio as photo_random,
)
from photosapi_client.api.default.photo_upload_albums_album_photos_post import ( from photosapi_client.api.default.photo_upload_albums_album_photos_post import (
asyncio_detailed as photo_upload, asyncio_detailed as photo_upload,
) )
@@ -39,6 +42,9 @@ from photosapi_client.api.default.video_get_videos_id_get import asyncio as vide
from photosapi_client.api.default.video_patch_videos_id_patch import ( from photosapi_client.api.default.video_patch_videos_id_patch import (
asyncio as video_patch, asyncio as video_patch,
) )
from photosapi_client.api.default.video_random_albums_album_videos_random_get import (
asyncio as video_random,
)
from photosapi_client.api.default.video_upload_albums_album_videos_post import ( from photosapi_client.api.default.video_upload_albums_album_videos_post import (
asyncio as video_upload, asyncio as video_upload,
) )
@@ -53,8 +59,10 @@ from photosapi_client.models.body_video_upload_albums_album_videos_post import (
) )
from photosapi_client.models.http_validation_error import HTTPValidationError from photosapi_client.models.http_validation_error import HTTPValidationError
from photosapi_client.models.photo import Photo from photosapi_client.models.photo import Photo
from photosapi_client.models.photo_search import PhotoSearch
from photosapi_client.models.token import Token from photosapi_client.models.token import Token
from photosapi_client.models.video import Video from photosapi_client.models.video import Video
from photosapi_client.models.video_search import VideoSearch
from photosapi_client.types import File from photosapi_client.types import File
from modules.http_client import http_session from modules.http_client import http_session

View File

@@ -1,33 +1,37 @@
import logging import logging
from datetime import datetime from datetime import datetime
from os import makedirs, path from os import makedirs, path
from random import choice from random import choice, sample
from shutil import rmtree from shutil import rmtree
from traceback import format_exc, print_exc from traceback import format_exc, print_exc
from typing import Union
from uuid import uuid4 from uuid import uuid4
import aiofiles import aiofiles
from aiohttp import ClientSession from aiohttp import ClientSession
from libbot.pyrogram.classes import PyroClient
from photosapi_client.errors import UnexpectedStatus from photosapi_client.errors import UnexpectedStatus
from PIL import Image from PIL import Image
from pyrogram.client import Client
from modules.api_client import ( from modules.api_client import (
File,
PhotoSearch,
VideoSearch,
authorize, authorize,
client, client,
photo_find,
photo_get, photo_get,
photo_patch, photo_patch,
video_find, photo_random,
video_get, video_get,
video_patch, video_patch,
video_random,
) )
from modules.database import col_sent, col_submitted from modules.database import col_sent, col_submitted
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
async def send_content(app: Client, http_session: ClientSession) -> None: async def send_content(app: PyroClient, http_session: ClientSession) -> None:
try: try:
try: try:
token = await authorize(http_session) token = await authorize(http_session)
@@ -40,25 +44,72 @@ async def send_content(app: Client, http_session: ClientSession) -> None:
try: try:
funcs = [] 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( if app.config["posting"]["types"]["photo"]:
( funcs.append((photo_random, photo_get, app.send_photo, photo_patch))
await func(
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"
)
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"], album=app.config["posting"]["api"]["album"],
caption="queue", caption="queue",
page_size=app.config["posting"]["page_size"],
client=client, client=client,
limit=1,
) )
).results ).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): except (KeyError, AttributeError, TypeError, IndexError):
logger.info(app._("post_empty", "console")) logger.info(app._("post_empty", "console"))
if app.config["reports"]["error"]: if app.config["reports"]["error"]:
@@ -67,6 +118,7 @@ async def send_content(app: Client, http_session: ClientSession) -> None:
app._("api_queue_empty", "message"), app._("api_queue_empty", "message"),
) )
return return
except (ValueError, UnexpectedStatus): except (ValueError, UnexpectedStatus):
if app.config["reports"]["error"]: if app.config["reports"]["error"]:
await app.send_message( await app.send_message(
@@ -75,30 +127,6 @@ async def send_content(app: Client, http_session: ClientSession) -> None:
) )
return 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()) tmp_dir = str(uuid4())
makedirs(path.join(app.config["locations"]["tmp"], tmp_dir), exist_ok=True) makedirs(path.join(app.config["locations"]["tmp"], tmp_dir), exist_ok=True)
@@ -111,12 +139,15 @@ async def send_content(app: Client, http_session: ClientSession) -> None:
await out_file.write(response.payload.read()) await out_file.write(response.payload.read())
logger.info( logger.info(
f"Candidate {media.filename} ({media.id}) is {path.getsize(path.join(app.config['locations']['tmp'], tmp_path))} bytes big", "Candidate %s (%s) is %s bytes big",
media.filename,
media.id,
path.getsize(path.join(app.config["locations"]["tmp"], tmp_path)),
) )
if ( if (
path.getsize(path.join(app.config["locations"]["tmp"], tmp_path)) > 5242880 path.getsize(path.join(app.config["locations"]["tmp"], tmp_path)) > 5242880
) and func is photo_find: ) and func[0] is photo_random:
image = Image.open(path.join(app.config["locations"]["tmp"], tmp_path)) image = Image.open(path.join(app.config["locations"]["tmp"], tmp_path))
width, height = image.size width, height = image.size
image = image.resize((int(width / 2), int(height / 2)), Image.ANTIALIAS) image = image.resize((int(width / 2), int(height / 2)), Image.ANTIALIAS)
@@ -138,7 +169,7 @@ async def send_content(app: Client, http_session: ClientSession) -> None:
if ( if (
path.getsize(path.join(app.config["locations"]["tmp"], tmp_path)) > 5242880 path.getsize(path.join(app.config["locations"]["tmp"], tmp_path)) > 5242880
) and func is photo_find: ) and func[0] is photo_random:
rmtree( rmtree(
path.join(app.config["locations"]["tmp"], tmp_dir), ignore_errors=True path.join(app.config["locations"]["tmp"], tmp_dir), ignore_errors=True
) )
@@ -178,23 +209,15 @@ async def send_content(app: Client, http_session: ClientSession) -> None:
caption = caption caption = caption
try: try:
if func is photo_find: sent = await func[2](
sent = await app.send_photo( app.config["posting"]["channel"],
app.config["posting"]["channel"], path.join(app.config["locations"]["tmp"], tmp_path),
path.join(app.config["locations"]["tmp"], tmp_path), caption=caption,
caption=caption, disable_notification=app.config["posting"]["silent"],
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: except Exception as exp:
logger.error( logger.error(
f"Could not send media {media.filename} ({media.id}) due to {exp}" "Could not send media %s (%s) due to %s", media.filename, media.id, exp
) )
if app.config["reports"]["error"]: if app.config["reports"]["error"]:
await app.send_message( await app.send_message(
@@ -216,8 +239,7 @@ async def send_content(app: Client, http_session: ClientSession) -> None:
} }
) )
func_patch = photo_patch if func is photo_find else video_patch await func[3](id=media.id, client=client, caption="sent")
await func_patch(id=media.id, client=client, caption="sent")
rmtree(path.join(app.config["locations"]["tmp"], tmp_dir), ignore_errors=True) rmtree(path.join(app.config["locations"]["tmp"], tmp_dir), ignore_errors=True)

View File

@@ -23,7 +23,7 @@ logger = logging.getLogger(__name__)
@Client.on_message( @Client.on_message(
~filters.scheduled & filters.private & filters.photo ~filters.scheduled & filters.private & filters.photo
| filters.video | filters.video
| filters.animation # | filters.animation
| filters.document | filters.document
) )
async def get_submission(app: PyroClient, msg: Message): async def get_submission(app: PyroClient, msg: Message):
@@ -103,27 +103,27 @@ async def get_submission(app: PyroClient, msg: Message):
save_tmp = False save_tmp = False
contents = msg.video.file_id, SubmissionType.VIDEO # , msg.video.file_name contents = msg.video.file_id, SubmissionType.VIDEO # , msg.video.file_name
if msg.animation is not None: # if msg.animation is not None:
logger.info( # logger.info(
"User %s is trying to submit an animation with name '%s' and size of %s MB", # "User %s is trying to submit an animation with name '%s' and size of %s MB",
msg.from_user.id, # msg.from_user.id,
msg.animation.file_name, # msg.animation.file_name,
msg.animation.file_size / 1024 / 1024, # msg.animation.file_size / 1024 / 1024,
) # )
if msg.animation.file_size > app.config["submission"]["file_size"]: # if msg.animation.file_size > app.config["submission"]["file_size"]:
await msg.reply_text( # await msg.reply_text(
app._("document_too_large", "message", locale=user_locale).format( # app._("document_too_large", "message", locale=user_locale).format(
str(app.config["submission"]["file_size"] / 1024 / 1024) # str(app.config["submission"]["file_size"] / 1024 / 1024)
), # ),
quote=True, # quote=True,
) # )
return # return
if msg.animation.file_size > app.config["submission"]["tmp_size"]: # if msg.animation.file_size > app.config["submission"]["tmp_size"]:
save_tmp = False # save_tmp = False
contents = ( # contents = (
msg.animation.file_id, # msg.animation.file_id,
SubmissionType.ANIMATION, # SubmissionType.ANIMATION,
) # , msg.animation.file_name # ) # , msg.animation.file_name
if msg.photo is not None: if msg.photo is not None:
logger.info( logger.info(