diff --git a/getstickers.py b/getstickers.py new file mode 100644 index 0000000..e651304 --- /dev/null +++ b/getstickers.py @@ -0,0 +1,141 @@ +import asyncio +from collections import defaultdict +import os +import zipfile +from telethon.tl.functions.messages import GetStickerSetRequest +from telethon.errors import MessageNotModifiedError +from pagermaid import working_dir +from telethon.tl.types import ( + DocumentAttributeFilename, + DocumentAttributeSticker, + InputMediaUploadedDocument, + InputPeerNotifySettings, + InputStickerSetID, + InputStickerSetShortName, + MessageMediaPhoto +) +from pagermaid.listener import listener +from pagermaid.utils import alias_command + +lottie_import = True +try: + from lottie.exporters.gif import export_gif + from lottie.importers.core import import_tgs +except ImportError: + lottie_import = False + + +@listener(is_plugin=True, outgoing=True, command=alias_command("getstickers"), + description="获取整个贴纸包的贴纸,任意值开启 tgs 转 gif 需要手动安装 pypi 依赖 lottie[gif] 。", + parameters="<任意值>") +async def getstickers(context): + tgs_gif = True + if len(context.parameter) == 0: + tgs_gif = False + if not os.path.isdir('data/sticker/'): + os.makedirs('data/sticker/') + if context.reply_to_msg_id: + reply_message = await context.get_reply_message() + if not reply_message.sticker: + await context.edit("请回复一张贴纸。") + return + sticker = reply_message.sticker + sticker_attrib = find_instance(sticker.attributes, DocumentAttributeSticker) + if not sticker_attrib.stickerset: + await context.edit("回复的贴纸不属于任何贴纸包。") + return + is_a_s = is_it_animated_sticker(reply_message) + file_ext_ns_ion = "webp" + if is_a_s: + file_ext_ns_ion = "tgs" + if tgs_gif and not lottie_import: + await context.reply('`lottie[gif]` 依赖未安装,tgs 无法转换为 gif ,进行标准格式导出。') + sticker_set = await context.client(GetStickerSetRequest(sticker_attrib.stickerset)) + pack_file = os.path.join('data/sticker/', sticker_set.set.short_name, "pack.txt") + if os.path.isfile(pack_file): + os.remove(pack_file) + # Sticker emojis + emojis = defaultdict(str) + for pack in sticker_set.packs: + for document_id in pack.documents: + emojis[document_id] += pack.emoticon + + async def download(sticker, emojis, path, file): + await context.client.download_media(sticker, file=os.path.join(path, file)) + with open(pack_file, "a") as f: + f.write(f"{{'image_file': '{file}','emojis':{emojis[sticker.id]}}},") + if file_ext_ns_ion == 'tgs' and lottie_import and tgs_gif: + animated = import_tgs(os.path.join(path, file)) + export_gif(animated, os.path.join(path, file)[:-3] + 'gif') + + pending_tasks = [ + asyncio.ensure_future( + download(document, emojis, 'data/sticker/' + sticker_set.set.short_name, + f"{i:03d}.{file_ext_ns_ion}") + ) for i, document in enumerate(sticker_set.documents) + ] + await context.edit( + f"正在下载 {sticker_set.set.short_name} 中的 {sticker_set.set.count} 张贴纸。。。") + num_tasks = len(pending_tasks) + while 1: + done, pending_tasks = await asyncio.wait(pending_tasks, timeout=2.5, + return_when=asyncio.FIRST_COMPLETED) + if file_ext_ns_ion == 'tgs' and lottie_import and tgs_gif: + try: + await context.edit( + f"正在下载/转换中,进度: {num_tasks - len(pending_tasks)}/{sticker_set.set.count}") + except MessageNotModifiedError: + pass + if not pending_tasks: + break + await context.edit("下载完毕,打包上传中。") + directory_name = sticker_set.set.short_name + os.chdir("data/sticker/") # 修改当前工作目录 + zipf = zipfile.ZipFile(directory_name + ".zip", "w", zipfile.ZIP_DEFLATED) + zipdir(directory_name, zipf) + zipf.close() + await context.client.send_file( + context.chat_id, + directory_name + ".zip", + caption=sticker_set.set.short_name, + force_document=True, + allow_cache=False, + reply_to=reply_message.id + ) + try: + os.remove(directory_name + ".zip") + os.remove(directory_name) + except: + pass + os.chdir(working_dir) + await context.delete() + else: + await context.edit("请回复一张贴纸。") + + +def find_instance(items, class_or_tuple): + for item in items: + if isinstance(item, class_or_tuple): + return item + return None + + +def is_it_animated_sticker(message): + try: + if message.media and message.media.document: + mime_type = message.media.document.mime_type + if "tgsticker" in mime_type: + return True + else: + return False + else: + return False + except: + return False + + +def zipdir(path, ziph): + for root, dirs, files in os.walk(path): + for file in files: + ziph.write(os.path.join(root, file)) + os.remove(os.path.join(root, file)) diff --git a/list.json b/list.json index c67226c..a4e5c57 100644 --- a/list.json +++ b/list.json @@ -348,7 +348,7 @@ "size": "4.0 kb", "supported": true, "des-short": "vip 捐赠用户功能", - "des": "命令:天气:baidu weather Pixiv:pixiv。与 weather 插件冲突" + "des": "命令:天气:weather Pixiv:pixiv 百度:baidu。与 weather 插件冲突" }, { "name": "calculator", @@ -529,6 +529,16 @@ "supported": false, "des-short": "打字带空格", "des": "需要 pypi 前置 jieba 。" + }, + { + "name": "getstickers", + "version": "1.0", + "section": "chat", + "maintainer": "xtaodada", + "size": "5.4 kb", + "supported": true, + "des-short": "贴纸包批量导出", + "des": "可选 pypi 前置 lottie[gif] 。" } ] }