sycgram/tools/stickers.py

219 lines
6.3 KiB
Python
Raw Normal View History

2022-04-06 14:39:27 +00:00
import asyncio
from math import floor
from typing import Optional
import emoji
from loguru import logger
from PIL import Image, UnidentifiedImageError
from pyrogram import Client
from pyrogram.errors import FloodWait, RPCError
from pyrogram.types import Message
from .constants import STICKER_BOT, STICKER_IMG
from .helpers import Parameters, delete_this
class StickerLocker:
"""贴纸指令🔒"""
def __init__(self) -> None:
self._lock = asyncio.Lock()
def get_lock(self) -> None:
return self._lock
sticker_locker = StickerLocker()
class StickerEvent:
"""贴纸对话事件"""
def __init__(self) -> None:
self._cond = asyncio.Condition()
def get_response(self) -> asyncio.Condition:
return self._cond
def wait(self):
return self._cond.wait()
def notify(self):
return self._cond.notify()
sticker_cond = StickerEvent()
class StickerAdder:
"""
新增贴纸的指令`-s`实现详细步骤
1解禁机器人(`@Stickers`)
2发送/cancel
3检测目标消息是否为贴纸
3-1转发贴纸到@Stickerss
3-2获取并发送emoji
3-3发送/done
3-4结束指令
4若不是则检测是否为图片或图片格式的文件
1转化图片
"""
def __init__(self, cli: Client, msg: Message) -> None:
self._cli = cli
self._msg = msg
self._bot_id = STICKER_BOT
self._count = 0
def is_finished(self, pkg_existed: bool) -> bool:
return (pkg_existed and self._count == 6) or \
(not pkg_existed and self._count == 8)
async def do_cancel(self) -> None:
"""取消原指令残留效果"""
self._count = 0
await self.send_message('/cancel')
async def send_message(self, text: str) -> None:
"""发送指令(或`emoji`)给贴纸"""
try:
await self._cli.send_message(
self._bot_id, text,
disable_notification=True)
except FloodWait as e:
await asyncio.sleep(e.x)
await self._cli.send_message(
self._bot_id, text,
disable_notification=True)
except RPCError as e:
logger.warning(e)
else:
await self.__wait_for()
async def send_emoji(self) -> None:
if self._msg.reply_to_message.sticker:
an_emoji = self._msg.reply_to_message.sticker.emoji
else:
_, arg = Parameters.get(self._msg)
if emoji.is_emoji(arg):
an_emoji = arg
else:
an_emoji = '⚡️'
await self.send_message(an_emoji)
async def send_retries(self, n: int) -> None:
try:
retry_text = f"⚠️ Retrying {n+1} times ..."
await self._msg.edit_text(retry_text)
logger.warning(retry_text)
except RPCError as e:
logger.warning(e)
finally:
await logger.complete()
async def upload_photo(self) -> Optional[bool]:
"""下载图片/图片文件,修剪后发送至@Stickers"""
img = await self._msg.reply_to_message.download(STICKER_IMG)
if not img:
return True
try:
resize_image(img)
except UnidentifiedImageError as e:
logger.warning(e)
return True
try:
await self._cli.send_document(
self._bot_id, document=img)
except FloodWait as e:
await asyncio.sleep(e.x)
await self._cli.send_document(
self._bot_id, document=img)
except RPCError as e:
logger.warning(e)
else:
await self.__wait_for()
async def edit_text(self, text, parse_mode: Optional[str] = None) -> None:
"""编辑消息"""
try:
await self._msg.edit_text(text, parse_mode=parse_mode)
except FloodWait as e:
await asyncio.sleep(e.x)
await self._msg.edit_text(text, parse_mode=parse_mode)
except RPCError as e:
logger.warning(e)
async def done(self, text: str, parse_mode: Optional[str] = None) -> None:
try:
await self.edit_text(text, parse_mode=parse_mode)
await asyncio.sleep(3.5)
await delete_this(self._msg)
except FloodWait as e:
await asyncio.sleep(e.x)
await self.edit_text(text, parse_mode=parse_mode)
await asyncio.sleep(3.5)
await delete_this(self._msg)
except RPCError as e:
logger.warning(e)
async def mark_as_read(self) -> None:
"""自动已读机器人的消息"""
try:
await self._cli.read_history(self._bot_id)
except FloodWait as e:
await asyncio.sleep(e.x)
await self._cli.read_history(self._bot_id)
except RPCError as e:
logger.warning(e)
async def __wait_for(self) -> None:
"""等待贴纸机器人(`@Stickers`)的回应"""
async with sticker_cond.get_response():
await asyncio.wait_for(sticker_cond.wait(), timeout=5)
logger.debug(
f"Counter of response from @Stickers is {self._count}"
)
self._count = self._count + 1
await self.mark_as_read()
def resize_image(photo: str):
with Image.open(photo) as img:
maxsize = (512, 512)
if img.width < 512 or img.height < 512:
w = img.width
h = img.height
if w > h:
scale = 512 / w
size1new = 512
size2new = h * scale
else:
scale = 512 / h
size1new = w * scale
size2new = 512
size_new = (floor(size1new), floor(size2new))
img = img.resize(size_new)
else:
img.thumbnail(maxsize)
img.save(photo, format='png')
return
def isEmoji(content):
if not content:
return False
if u"\U0001F600" <= content <= u"\U0001F64F":
return True
elif u"\U0001F300" <= content <= u"\U0001F5FF":
return True
elif u"\U0001F680" <= content <= u"\U0001F6FF":
return True
elif u"\U0001F1E0" <= content <= u"\U0001F1FF":
return True
else:
return False