diff --git a/royalnet/bots/telegram.py b/royalnet/bots/telegram.py index 10036cc5..797feef0 100644 --- a/royalnet/bots/telegram.py +++ b/royalnet/bots/telegram.py @@ -3,6 +3,7 @@ import asyncio import typing import logging as _logging import sys +import re from ..commands import NullCommand from ..utils import asyncify, Call, Command from ..network import RoyalnetLink, Message diff --git a/royalnet/commands/diario.py b/royalnet/commands/diario.py index d6d41d6b..f39d8140 100644 --- a/royalnet/commands/diario.py +++ b/royalnet/commands/diario.py @@ -4,8 +4,7 @@ import telegram import typing import os import aiohttp -from urllib.parse import quote -from ..utils import Command, CommandArgs, Call, InvalidInputError, InvalidConfigError, ExternalError +from ..utils import Command, Call, InvalidInputError, InvalidConfigError, ExternalError from ..database.tables import Royal, Diario, Alias from ..utils import asyncify @@ -19,6 +18,29 @@ class DiarioCommand(Command): require_alchemy_tables = {Royal, Diario, Alias} + async def _telegram_to_imgur(self, photosizes: typing.List[telegram.PhotoSize], caption="") -> str: + # Select the largest photo + largest_photo = sorted(photosizes, key=lambda p: p.width * p.height)[-1] + # Get the photo url + photo_file: telegram.File = await asyncify(largest_photo.get_file) + # Forward the url to imgur, as an upload + try: + imgur_api_key = os.environ["IMGUR_CLIENT_ID"] + except KeyError: + raise InvalidConfigError("Missing IMGUR_CLIENT_ID envvar, can't upload images to imgur.") + async with aiohttp.request("post", "https://api.imgur.com/3/upload", data={ + "image": photo_file.file_path, + "type": "URL", + "title": "Diario image", + "description": caption + }, headers={ + "Authorization": f"Client-ID {imgur_api_key}" + }) as request: + response = await request.json() + if not response["success"]: + raise ExternalError("imgur returned an error in the image upload.") + return response["data"]["link"] + async def common(self, call: Call): # Find the creator of the quotes creator = await call.get_author() @@ -86,31 +108,13 @@ class DiarioCommand(Command): # Check if there's an image associated with the reply photosizes: typing.Optional[typing.List[telegram.PhotoSize]] = reply.photo if photosizes: - # Select the largest photo - largest_photo = sorted(photosizes, key=lambda p: p.width*p.height)[-1] - # Get the photo url - photo_file: telegram.File = await asyncify(largest_photo.get_file) - # Forward the url to imgur, as an upload - try: - imgur_api_key = os.environ["IMGUR_CLIENT_ID"] - except KeyError: - raise InvalidConfigError("Missing IMGUR_CLIENT_ID envvar, can't upload images to imgur.") - async with aiohttp.request("post", "https://api.imgur.com/3/upload", params={ - "image": quote(photo_file.file_path), - "type": "URL", - "title": "Diario image", - "description": reply.caption if reply.caption is not None else "" - }, headers={ - "Authorization": f"Client-ID {imgur_api_key}" - }) as request: - response = await request.json() - if not response["success"]: - raise ExternalError("imgur returned an error in the image upload.") - media_url = response["data"]["link"] + # Python is doing some weird stuff here, self._telegram_to_imgur appears to be unbound? + # noinspection PyArgumentList + media_url = await self._telegram_to_imgur(self, photosizes, text if text is not None else "") else: media_url = None # Ensure there is a text or an image - if not text or media_url: + if not (text or media_url): raise InvalidInputError("Missing text.") # Find the Royalnet account associated with the sender quoted_tg = await asyncify(call.session.query(call.alchemy.Telegram).filter_by(tg_id=reply.from_user.id).one_or_none) @@ -166,27 +170,9 @@ class DiarioCommand(Command): # Check if there's an image associated with the reply photosizes: typing.Optional[typing.List[telegram.PhotoSize]] = message.photo if photosizes: - # Select the largest photo - largest_photo = sorted(photosizes, key=lambda p: p.width * p.height)[-1] - # Get the photo url - photo_file: telegram.File = await asyncify(largest_photo.get_file) - # Forward the url to imgur, as an upload - try: - imgur_api_key = os.environ["IMGUR_CLIENT_ID"] - except KeyError: - raise InvalidConfigError("Missing IMGUR_CLIENT_ID envvar, can't upload images to imgur.") - async with aiohttp.request("post", "https://api.imgur.com/3/upload", params={ - "image": quote(photo_file.file_path), - "type": "URL", - "title": "Diario image", - "description": message.caption - }, headers={ - "Authorization": f"Client-ID {imgur_api_key}" - }) as request: - response = await request.json() - if not response["success"]: - raise ExternalError("imgur returned an error in the image upload.") - media_url = response["data"]["link"] + # Python is doing some weird stuff here, self._telegram_to_imgur appears to be unbound? + # noinspection PyArgumentList + media_url = await self._telegram_to_imgur(self, photosizes, text if text is not None else "") else: media_url = None # Ensure there is a text or an image @@ -199,7 +185,7 @@ class DiarioCommand(Command): text=text, context=context, timestamp=timestamp, - media_url=None, + media_url=media_url, spoiler=spoiler) call.session.add(diario) await asyncify(call.session.commit) diff --git a/royalnet/database/tables/diario.py b/royalnet/database/tables/diario.py index 7758e88b..69be1013 100644 --- a/royalnet/database/tables/diario.py +++ b/royalnet/database/tables/diario.py @@ -17,7 +17,7 @@ class Diario: creator_id = Column(Integer, ForeignKey("royals.uid"), nullable=False) quoted_account_id = Column(Integer, ForeignKey("royals.uid")) quoted = Column(String) - text = Column(Text, nullable=False) + text = Column(Text) context = Column(Text) timestamp = Column(DateTime, nullable=False) media_url = Column(String) @@ -34,11 +34,14 @@ class Diario: text = f"Riga #{self.diario_id}" text += f" (salvata da {str(self.creator)}" text += f" il {self.timestamp.strftime('%Y-%m-%d %H:%M')}):\n" - if self.spoiler: - hidden = re.sub("\w", "█", self.text) - text += f"\"{hidden}\"\n" - else: - text += f"[b]\"{self.text}\"[/b]\n" + if self.media_url is not None: + text += f"{self.media_url}\n" + if self.text is not None: + if self.spoiler: + hidden = re.sub(r"\w", "█", self.text) + text += f"\"{hidden}\"\n" + else: + text += f"[b]\"{self.text}\"[/b]\n" if self.quoted_account is not None: text += f" —{str(self.quoted_account)}" elif self.quoted is not None: