async def request_episodes_confirm(bot: Amime, callback: CallbackQuery): user = callback.from_user lang = callback._lang anime_id = int(callback.matches[0].group(1)) language = callback.matches[0].group(2) anime = await anilist.AsyncClient().get(anime_id) is_collaborator = await filters.collaborator(bot, callback) or bot.is_sudo(user) requests = await Requests.filter(item=anime_id, type="anime") requests = sorted(requests, key=lambda request: request.id) now_date = datetime.datetime.now().replace(tzinfo=datetime.timezone.utc) if not is_collaborator and len(requests) > 0: request = requests[-1] request_date = request.datetime date = now_date - request_date if date.seconds < (1 * 60 * 60 * 24): await callback.answer( lang.requested_in_last_24h_alert( date=request_date.strftime("%H:%M:%S - %d/%m/%Y")), show_alert=True, ) return await Requests.create( user=user.id, item=anime_id, type="anime", datetime=now_date, done=False, ) text = "<b>New request</b>" text += f"\n<b>From</b>: {user.mention()}" text += "\n<b>Anime</b>:" text += f"\n <b>ID</b>: <code>{anime.id}</code>" text += f"\n <b>Name</b>: <code>{anime.title.romaji}</code>" text += ( f"\n <b>Language</b>: <code>{lang.strings[language]['LANGUAGE_NAME']}</code>" ) text += "\n\n#REQUEST" await bot.send_message( CHATS["requests"], text, reply_markup=ikb([[("🆙 Get", f"request get anime {anime_id} {language}")]]), ) await callback.answer(lang.request_sent_alert, show_alert=True) matches = re.match(r"(\d+) (\d+)\s?(\d+)?", f"{anime_id} {user.id}") callback.matches = [matches] await anime_view(bot, callback)
async def on_remove_plugin(c: Client, cq: CallbackQuery): lang = cq._lang basename = cq.matches[0]["basename"] plugin_type = cq.matches[0]["plugin_type"] pg = cq.matches[0]["page"] if basename not in plugins[plugin_type]: return await cq.answer(lang.plugin_not_found(name=basename)) plugin = plugins[plugin_type][basename] inactive = await get_inactive_plugins(plugins) if not os.path.exists(plugin["filename"]): return await cq.edit(lang.plugin_not_exists_on_server) if plugin["notation"] in inactive: inactive = [x for x in inactive if x != plugin["notation"]] await Config.get(key="INACTIVE_PLUGINS" ).update(value=json.dumps(inactive)) try: module = importlib.import_module(plugin["notation"]) except Exception as e: os.remove(plugin["filename"]) return await cq.edit(lang.plugin_could_not_load(e=e)) functions = [*filter(callable, module.__dict__.values())] functions = [*filter(lambda f: hasattr(f, "handler"), functions)] client = (user, bot)[plugin_type == "bot"] for f in functions: client.remove_handler(*f.handler) del plugins[plugin_type][basename] os.remove(plugin["filename"]) await cq.answer(lang.plugin_removed(name=basename)) cq.matches = [{"page": pg, "type": plugin_type}] await on_list_plugins_type(c, cq)
async def anime_episode_delete(bot: Amime, callback: CallbackQuery): message = callback.message user = callback.from_user lang = callback._lang anime_id = int(callback.matches[0].group(1)) season = int(callback.matches[0].group(2)) number = int(callback.matches[0].group(3)) subtitled = bool(int(callback.matches[0].group(4))) language = callback.matches[0].group(5) page = int(callback.matches[0].group(6)) episodes = [] if number == -1: keyboard = [ [ ( lang.confirm_button, f"manage episode delete {anime_id} {season} -2 {int(subtitled)} {language} {page}", ), ( lang.cancel_button, f"manage anime {anime_id} {season} {int(subtitled)} {language} {page}", ), ], ] await message.edit_text( lang.confirm_text, reply_markup=ikb(keyboard), ) return elif number == -2: episodes = await Episodes.filter( anime=anime_id, season=season, language=language, subtitled=subtitled, ) logger.debug( "%s deleted season %s of the anime %s (%s)", user.first_name, season, anime_id, language, ) else: episodes = [ await Episodes.get( anime=anime_id, season=season, number=number, language=language, subtitled=subtitled, ) ] logger.debug( "%s deleted episode %s of the anime %s (%s)", user.first_name, number, anime_id, language, ) for episode in episodes: notification = await Notifications.get_or_none(item=anime_id, type="anime", season=season, number=number, language=language) if notification is not None: await notification.delete() await episode.delete() await callback.answer(lang.confirm_delete_episode_alert, show_alert=True) matches = re.search( r"(\d+) (\d+) (\d+) (\w+) (\d+)", f"{anime_id} {season} {int(subtitled)} {language} {page}", ) callback.matches = [matches] await anime_manage(bot, callback)
async def anime_episode_save(bot: Amime, callback: CallbackQuery): user = callback.from_user lang = callback._lang anime_id = int(callback.matches[0].group(1)) season = int(callback.matches[0].group(2)) subtitled = bool(int(callback.matches[0].group(3))) language = callback.matches[0].group(4) page = int(callback.matches[0].group(5)) episode = EPISODES[str(user.id)][str(anime_id)] logger.debug( "%s is edited/saved episode %s of the anime %s (%s)", user.first_name, episode["number"], anime_id, language, ) episode["anime"] = anime_id episode["season"] = season episode["language"] = language episode["added_by"] = str(user.id) id = -1 if "id" in episode.keys(): id = episode["id"] video = episode["video"] if isinstance(episode["video"], Document): episode["file_id"] = "" elif isinstance(episode["video"], Video): episode["file_id"] = episode["video"].file_id del episode["video"] number = episode["number"] if "id" in episode.keys(): episode_db = await Episodes.get(id=episode["id"]) del episode["id"] episode_db.update_from_dict(episode) await episode_db.save() else: episode_db = await Episodes.create(**episode) id = episode_db.id now_date = datetime.datetime.now().replace( tzinfo=datetime.timezone.utc) await Notifications.create( item=anime_id, type="anime", season=season, number=number, language=language, datetime=now_date, ) if "update_video" in episode.keys() and episode["update_video"] is True: await bot.video_queue.add(id, video) await callback.answer(lang.confirm_save_episode_alert, show_alert=True) matches = re.search( r"(\d+) (\d+) (\d+) (\w+) (\d+)", f"{anime_id} {season} {int(subtitled)} {language} {page}", ) callback.matches = [matches] await anime_manage(bot, callback) del EPISODES[str(user.id)][str(anime_id)]
async def anime_manage(bot: Amime, callback: CallbackQuery): message = callback.message chat = message.chat user = callback.from_user lang = callback._lang anime_id = int(callback.matches[0].group(1)) season = int(callback.matches[0].group(2)) subtitled = bool(int(callback.matches[0].group(3))) language = callback.matches[0].group(4) page = int(callback.matches[0].group(5)) if str(user.id) in VIDEOS.keys() and str(anime_id) in VIDEOS[str( user.id)].keys(): chat.cancel_listener() del VIDEOS[str(user.id)][str(anime_id)] buttons = [ ( f"{lang.language_button}: {lang.strings[language]['LANGUAGE_NAME']}", f"manage anime language {anime_id} {season} {int(subtitled)} {language} {page}", ), ( f"{lang.season_button}: {season}", f"manage anime season {anime_id} {season} {int(subtitled)} {language} {page}", ), ( f"{lang.subtitled_button}: {lang.yes if subtitled else lang.no}", f"manage anime {anime_id} {season} {int(not subtitled)} {language} {page}", ), ( lang.add_button, f"manage episode {anime_id} {season} -1 {int(subtitled)} {language} {page}", ), ] episodes = await Episodes.filter(anime=anime_id, season=season, language=language, subtitled=subtitled) episodes = sorted(episodes, key=lambda episode: episode.number) if len(episodes) >= 2: buttons.append(( lang.del_season_button, f"manage episode delete {anime_id} {season} -1 {int(subtitled)} {language} {page}", )) else: if page > 0: page -= 1 matches = re.search( r"(\d+) (\d+) (\d+) (\w+) (\d+)", f"{anime_id} {season} {int(subtitled)} {language} {page}", ) callback.matches = [matches] await anime_manage(bot, callback) return buttons.append(( lang.add_in_batch_button, f"manage episode batch {anime_id} {season} {int(subtitled)} {language} {page}", )) notifications = await Notifications.filter( item=anime_id, type="anime", language=language, ) if len(notifications) > 0: buttons.append(( lang.notify_users_button, f"notify episodes {anime_id} {season} {int(subtitled)} {language} {page}", )) keyboard = array_chunk(buttons, 2) layout = Pagination( episodes, item_data=lambda i, pg: f"manage episode {i.anime} {i.season} {i.number} {int(subtitled)} {language} {pg}", item_title=lambda i, pg: f"📝 {i.number}", page_data=lambda pg: f"manage anime {anime_id} {season} {int(subtitled)} {language} {pg}", ) lines = layout.create(page, lines=5, columns=3) if len(lines) > 0: keyboard += lines keyboard.append([(lang.back_button, f"anime {anime_id}")]) if bool(message.photo): await message.edit_text( lang.manage_anime_text, reply_markup=ikb(keyboard), ) else: await callback.edit_message_media( InputMediaPhoto( f"https://img.anili.st/media/{anime_id}", caption=lang.manage_anime_text, ), reply_markup=ikb(keyboard), )
async def anime_episode_edit(bot: Amime, callback: CallbackQuery): message = callback.message chat = message.chat user = callback.from_user lang = callback._lang item = callback.matches[0].group(1) anime_id = int(callback.matches[0].group(2)) season = int(callback.matches[0].group(3)) number = int(callback.matches[0].group(4)) subtitled = bool(int(callback.matches[0].group(5))) language = callback.matches[0].group(6) page = int(callback.matches[0].group(7)) episode = EPISODES[str(user.id)][str(anime_id)] keyboard = [ [ ( lang.cancel_button, f"manage episode {anime_id} {season} {number} {int(subtitled)} {language} {page}", ), ], ] await message.edit_text( lang.send_me_the_item_text(item=lang.strings[lang.code][item].lower()), reply_markup=ikb(keyboard), ) answer = None if item == "video": while True: try: answer = await chat.listen(filters.video | filters.document) except ListenerCanceled: return if bool(answer.video): duration = answer.video.duration if duration <= 30: try: await callback.answer(lang.very_short_video_alert, show_alert=True) continue except QueryIdInvalid: sent = await answer.reply_text( lang.very_short_video_alert) await asyncio.sleep(3) await sent.delete() continue episode["video"] = answer.video episode["duration"] = duration // 60 elif bool(answer.document): episode["video"] = answer.document if bool(answer.forward_from ) and answer.forward_from.id == bot.me.id: episode["update_video"] = False else: episode["update_video"] = True break else: if item == "number": while True: try: answer = await chat.listen(filters.text) except ListenerCanceled: return ep = answer.text.split("-") if not int(ep[0]) == number: number = ep[0] if len(ep) > 1: episode["unified_until"] = ep[1] else: episode["unified_until"] = "0" answers = [] if bool(await Episodes.get_or_none( anime=anime_id, season=season, number=number, language=language, )): try: await callback.answer( lang.episode_already_exists_alert, show_alert=True) except QueryIdInvalid: sent = await answer.reply_text( lang.episode_already_exists_alert) await asycio.sleep(3) await sent.delete() finally: continue number = answer.text answers.append(answer) for _answer in answers: try: await _answer.delete() await asyncio.sleep(1) except BaseException: pass break else: try: answer = await chat.listen(filters.text) except ListenerCanceled: return episode[item] = answer.text try: await answer.delete() except BaseException: pass EPISODES[str(user.id)][str(anime_id)] = episode matches = re.search( r"(\d+) (\d+) (\-?\d+) (\d+) (\w+) (\d+)", f"{anime_id} {season} {number} {int(subtitled)} {language} {page}", ) callback.matches = [matches] await anime_episode(bot, callback)