import os import time import html import asyncio import datetime import tempfile from decimal import Decimal from urllib.parse import quote as urlencode from pyrogram import Client, filters from .. import config, help_dict, log_errors, session, progress_callback, public_log_errors @Client.on_message(~filters.sticker & ~filters.via_bot & ~filters.edited & filters.me & filters.command(['trace', 'tracemoe', 'whatanime', 'wa', 'wait'], prefixes=config['config']['prefixes'])) @log_errors @public_log_errors async def whatanime(client, message): media = message.photo or message.animation or message.video or message.sticker or message.document if not media: reply = message.reply_to_message if not getattr(reply, 'empty', True): media = reply.photo or reply.animation or reply.video or reply.sticker or reply.document if not media: await message.reply_text('Photo or GIF or Video or Sticker required') return with tempfile.TemporaryDirectory() as tempdir: reply = await message.reply_text('Downloading...') path = await client.download_media(media, file_name=os.path.join(tempdir, '0'), progress=progress_callback, progress_args=(reply, 'Downloading...', False)) new_path = os.path.join(tempdir, '1.png') proc = await asyncio.create_subprocess_exec('ffmpeg', '-i', path, '-frames:v', '1', new_path) await proc.communicate() await reply.edit_text('Uploading...') with open(new_path, 'rb') as file: async with session.post('https://trace.moe/api/search', data={'image': file}) as resp: json = await resp.json() if isinstance(json, str): await reply.edit_text(html.escape(json)) else: try: match = json['docs'][0] except IndexError: await reply.edit_text('No match') else: nsfw = match['is_adult'] title_native = match['title_native'] title_english = match['title_english'] title_romaji = match['title_romaji'] synonyms = ', '.join(match['synonyms']) filename = match['filename'] tokenthumb = match['tokenthumb'] anilist_id = match['anilist_id'] episode = match['episode'] similarity = match['similarity'] from_time = str(datetime.timedelta(seconds=match['from'])).split('.', 1)[0].rjust(8, '0') to_time = str(datetime.timedelta(seconds=match['to'])).split('.', 1)[0].rjust(8, '0') at_time = match['at'] text = f'{title_romaji}' if title_english: text += f' ({title_english})' if title_native: text += f' ({title_native})' if synonyms: text += f'\nSynonyms: {synonyms}' text += f'\nSimilarity: {(Decimal(similarity) * 100).quantize(Decimal(".01"))}%\n' if episode: text += f'Episode: {episode}\n' if nsfw: text += 'Hentai/NSFW: Yes' async def _send_preview(): url = f'https://media.trace.moe/video/{anilist_id}/{urlencode(filename)}?t={at_time}&token={tokenthumb}' with tempfile.NamedTemporaryFile() as file: async with session.get(url) as resp: while True: chunk = await resp.content.read(10) if not chunk: break file.write(chunk) file.seek(0) try: await reply.reply_video(file.name, caption=f'{from_time} - {to_time}') except Exception: await reply.reply_text('Cannot send preview :/') await asyncio.gather(reply.edit_text(text, disable_web_page_preview=True), _send_preview()) help_dict['whatanime'] = ('WhatAnime', '''{prefix}whatanime (as caption of Photo/GIF/Video/Sticker or reply) - Reverse searches anime, thanks to trace.moe Aliases: {prefix}trace, {prefix}tracemoe, {prefix}wa, {prefix}wait''')