async def anilist_airing(message, strings): query = get_args_str(message) if query.isdecimal(): anime_id = int(query) else: try: async with anilist.AsyncClient() as client: results = await client.search(query, "anime", 1) anime_id = results[0].id except IndexError: return await message.reply(strings["search_err"]) async with anilist.AsyncClient() as client: anime = await client.get(anime_id) if not anime: return await message.reply(strings["search_get_err"].format( type="anime", id=anime_id)) text = f"<b>{anime.title.romaji}</b> (<code>{anime.title.native}</code>)" text += strings["id"].format(id=anime.id) text += strings["anime_type"].format(type=anime.format) if hasattr(anime, "next_airing"): airing_time = anime.next_airing.time_until * 1000 text += strings["airing_episode"].format(ep=anime.next_airing.episode) text += strings["airing_time"].format(time=t(airing_time)) else: text += strings["airing_episode"].format(ep=anime.episodes) text += strings["airing_time"].format(time="<code>N/A</code>") if hasattr(anime, "banner"): await message.reply_photo(photo=anime.banner, caption=text) else: await message.reply(text)
async def anilist_character(c: Korone, m: Message): query = m.matches[0]["search"] if query.isdecimal(): character_id = int(query) else: try: async with anilist.AsyncClient() as client: results = await client.search(query, "char", page=1, limit=1) character_id = results[0].id except IndexError: return await m.reply_text( "Algo deu errado, verifique sua pesquisa e tente novamente!" ) async with anilist.AsyncClient() as client: character = await client.get(character_id, "char") if not character: return await m.reply_text( f"Desculpe! Nenhum <b>personagem</b> com o ID <code>{character_id}</code> foi encontrado..." ) if hasattr(character, "description"): description = character.description description = description.replace("__", "**") description = description.replace("~", "~~") if len(character.description) > 700: description = f"{description[0:500]}[...]" text = f"<b>{character.name.full}</b> (<code>{character.name.native}</code>)" text += f"\n<b>ID:</b> <code>{character.id}</code>" if hasattr(character, "favorites"): text += f"\n<b>Favoritos:</b> <code>{character.favorites}</code>" if hasattr(character, "description"): text += f"\n\n<b>Sobre:</b>\n{html.escape(description)}" keyboard = [[("Mais informações", character.url, "url")]] if hasattr(character, "image"): if hasattr(character.image, "large"): photo = character.image.large elif hasattr(character.image, "medium"): photo = character.image.medium await m.reply_photo( photo=photo, caption=text, reply_markup=c.ikb(keyboard), parse_mode="combined", ) else: await m.reply_text( text, reply_markup=c.ikb(keyboard), parse_mode="combined", )
async def anilist_manga(c: Korone, m: Message): query = m.matches[0]["search"] if query.isdecimal(): manga_id = int(query) else: try: async with anilist.AsyncClient() as client: results = await client.search(query, "manga", page=1, limit=1) manga_id = results[0].id except IndexError: return await m.reply_text( "Algo deu errado, verifique sua pesquisa e tente novamente!" ) async with anilist.AsyncClient() as client: manga = await client.get(manga_id, "manga") if not manga: return await m.reply_text( f"Desculpe! Nenhum <b>mangá</b> com o ID <code>{manga_id}</code> foi encontrado..." ) if hasattr(manga, "description"): if len(manga.description) > 700: desc = f"<b>Descrição curta:</b> <i>{manga.description_short}</i>[...]" else: desc = f"<b>Descrição:</b> <i>{manga.description}</i>" text = f"<b>{manga.title.romaji}</b> {f'(<code>{manga.title.native}</code>)' if hasattr(manga.title, 'native') else ''}\n" text += f"<b>ID:</b> <code>{manga.id}</code>\n" if hasattr(manga, "status"): text += f"<b>Estado:</b> <code>{manga.status}</code>\n" if hasattr(manga, "chapters"): text += f"<b>Capítulos:</b> <code>{manga.chapters}</code>\n" if hasattr(manga, "volumes"): text += f"<b>Volumes:</b> <code>{manga.volumes}</code>\n" if hasattr(manga.score, "average"): text += f"<b>Pontuação:</b> <code>{manga.score.average}</code>\n" if hasattr(manga, "genres"): text += ( f"<b>Gêneros:</b> <code>{', '.join(str(x) for x in manga.genres)}</code>\n" ) if manga.status.lower() != "not_yet_released": text += f"<b>Início:</b> <code>{manga.start_date.day if hasattr(manga.start_date, 'day') else 0}/{manga.start_date.month if hasattr(manga.start_date, 'month') else 0}/{manga.start_date.year if hasattr(manga.start_date, 'year') else 0}</code>\n" if manga.status.lower() not in ["not_yet_released", "releasing"]: text += f"<b>Finalização:</b> <code>{manga.end_date.day if hasattr(manga.end_date, 'day') else 0}/{manga.end_date.month if hasattr(manga.end_date, 'month') else 0}/{manga.end_date.year if hasattr(manga.end_date, 'year') else 0}</code>\n" if hasattr(manga, "description"): text += f"\n{desc}" keyboard = [[("Mais informações", manga.url, "url")]] await m.reply_photo( photo=f"https://img.anili.st/media/{manga.id}", caption=text, reply_markup=c.ikb(keyboard), )
async def anilist_manga(message, strings): query = get_args_str(message) if query.isdecimal(): manga_id = int(query) else: try: async with anilist.AsyncClient() as client: results = await client.search(query, "manga", 1) manga_id = results[0].id except IndexError: return await message.reply(strings["search_err"]) async with anilist.AsyncClient() as client: manga = await client.get(manga_id, "manga") if not manga: return await message.reply(strings["search_get_err"].format( type="manga", id=manga_id)) if hasattr(manga, "description"): if len(manga.description) > 700: desc = strings["short_desc"].format(desc=manga.description_short) else: desc = strings["desc"].format(desc=manga.description) text = f"<b>{manga.title.romaji}</b> (<code>{manga.title.native}</code>)" text += strings["id"].format(id=manga.id) if hasattr(manga.start_date, "year"): text += strings["manga_start"].format(date=manga.start_date.year) if hasattr(manga, "status"): text += strings["status"].format(status=manga.status) if hasattr(manga, "chapters"): text += strings["manga_chapters"].format(chapters=manga.chapters) if hasattr(manga, "volumes"): text += strings["manga_volumes"].format(vol=manga.volumes) if hasattr(manga.score, "average"): text += strings["score"].format(score=manga.score.average) if hasattr(manga, "genres"): text += strings["genres"].format( genres=f" <code>{', '.join(str(x) for x in manga.genres)}</code>\n" ) if hasattr(manga, "description"): text += f"\n{desc.replace('<br>', '')}" keyboard = InlineKeyboardMarkup().add( InlineKeyboardButton(text=strings["more_info"], url=manga.url)) await message.reply_photo( photo=f"https://img.anili.st/media/{manga.id}", caption=text, reply_markup=keyboard, )
async def anilist_character(message, strings): query = get_args_str(message) if query.isdecimal(): character_id = int(query) else: try: async with anilist.AsyncClient() as client: results = await client.search(query, "char", 1) character_id = results[0].id except IndexError: return await message.reply(strings["search_err"]) async with anilist.AsyncClient() as client: character = await client.get(character_id, "char") if not character: return await message.reply(strings["search_get_err"].format( type="character", id=character_id)) if hasattr(character, "description"): desc = character.description desc = desc.replace("__", "") desc = desc.replace("**", "") desc = desc.replace("~", "") desc = re.sub(re.compile(r"<.*?>"), "", desc) if len(character.description) > 700: desc = desc[0:500] + "[...]" desc = strings["char_desc"].format(desc=desc) else: desc = strings["char_desc"].format(desc=desc) text = f"<b>{character.name.full}</b> (<code>{character.name.native}</code>)" text += strings["id"].format(id=character.id) if hasattr(character, "favorites"): text += strings["favorites"].format(favs=character.favorites) if hasattr(character, "description"): text += f"\n\n{desc}" keyboard = InlineKeyboardMarkup().add( InlineKeyboardButton(text=strings["more_info"], url=character.url)) if hasattr(character, "image"): await message.reply_photo( photo=character.image.large, caption=text, reply_markup=keyboard, ) else: await message.reply(text, reply_markup=keyboard)
async def test_get(id, content_type): client = anilist.AsyncClient() if "list" in content_type: assert await client.get(id, content_type, pagination=True) is not None assert await client.get(id, content_type, pagination=False) is not None else: assert await client.get(id, content_type) is not None
async def manga_view_more(bot: Amime, callback: CallbackQuery): message = callback.message user = callback.from_user lang = callback._lang manga_id = int(callback.matches[0].group(1)) user_id = int(callback.matches[0].group(2)) if user_id != user.id: return async with anilist.AsyncClient() as client: manga = await client.get(manga_id, "manga") buttons = [ (lang.description_button, f"manga description {manga_id} {user_id} 1"), (lang.characters_button, f"manga characters {manga_id} {user_id}"), (lang.studios_button, f"manga studios {manga_id} {user_id}"), ] buttons.append(("🐢 Anilist", manga.url, "url")) keyboard = array_chunk(buttons, 2) keyboard.append([(lang.back_button, f"manga {manga_id} {user_id}")]) await message.edit_text( lang.view_more_text, reply_markup=ikb(keyboard), )
async def manga_favorites(bot: Amime, callback: CallbackQuery): page = int(callback.matches[0]["page"]) message = callback.message user = callback.from_user lang = callback._lang keyboard = [] async with anilist.AsyncClient() as client: favorites = await Favorites.filter(user=user.id, type="manga") results = [] for favorite in favorites: manga = await client.get(favorite.item, "manga") results.append((favorite, manga)) layout = Pagination( results, item_data=lambda i, pg: f"manga {i[0].item}", item_title=lambda i, pg: i[1].title.romaji, page_data=lambda pg: f"favorites manga {pg}", ) lines = layout.create(page, lines=8) if len(lines) > 0: keyboard += lines keyboard.append([(lang.back_button, "manga")]) await message.edit_text( lang.favorites_text, reply_markup=ikb(keyboard), )
async def anime_view_characters(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)) user_id = int(callback.matches[0].group(2)) if user_id != user.id: return async with anilist.AsyncClient() as client: anime = await client.get(anime_id, "anime") keyboard = [ [ (lang.back_button, f"anime more {anime_id} {user_id}"), ], ] text = lang.characters_text characters = sorted(anime.characters, key=lambda character: character.id) for character in characters: text += f"\n• <code>{character.id}</code> - <a href='https://t.me/{bot.me.username}/?start=character_{character.id}'>{character.name.full}</a> (<i>{character.role}</i>)" await message.edit_text( text, reply_markup=ikb(keyboard), )
async def anime_view_more(bot: Amime, callback: CallbackQuery): message = callback.message user = callback.from_user lang = callback._lang anime_id = int(callback.matches[0].group(1)) user_id = int(callback.matches[0].group(2)) if user_id != user.id: return async with anilist.AsyncClient() as client: anime = await client.get(anime_id, "anime") buttons = [ (lang.description_button, f"anime description {anime_id} {user_id} 1"), (lang.characters_button, f"anime characters {anime_id} {user_id}"), (lang.studios_button, f"anime studios {anime_id} {user_id}"), ] if hasattr(anime, "trailer"): if hasattr(anime.trailer, "url"): buttons.append((lang.trailer_button, anime.trailer.url, "url")) buttons.append(("🐢 Anilist", anime.url, "url")) keyboard = array_chunk(buttons, 2) keyboard.append([(lang.back_button, f"anime {anime_id} {user_id}")]) await message.edit_text( lang.view_more_text, reply_markup=ikb(keyboard), )
async def anilist_airing(c: Korone, m: Message): query = m.matches[0]["search"] if query.isdecimal(): anime_id = int(query) else: try: async with anilist.AsyncClient() as client: results = await client.search(query, "anime", page=1, limit=1) anime_id = results[0].id except IndexError: return await m.reply_text( "Algo deu errado, verifique sua pesquisa e tente novamente!" ) async with anilist.AsyncClient() as client: anime = await client.get(anime_id) if not anime: return await m.reply_text( f"Desculpe! Nenhum <b>anime</b> com o ID <code>{anime_id}</code> foi encontrado..." ) text = f"<b>{anime.title.romaji}</b> {f'(<code>{anime.title.native}</code>)' if hasattr(anime.title, 'native') else ''}\n" text += f"<b>ID:</b> <code>{anime.id}</code>\n" text += f"<b>Tipo:</b> <code>{anime.format}</code>\n" if hasattr(anime, "next_airing"): airing_time = anime.next_airing.time_until * 1000 text += f"<b>Episódio:</b> <code>{anime.next_airing.episode}</code>\n" text += f"<b>Exibição em:</b> <code>{t(airing_time)}</code>" else: episodes = anime.episodes if hasattr(anime, "episodes") else "N/A" text += f"<b>Episódio:</b> <code>{episodes}</code>\n" text += "<b>Exibição em:</b> <code>N/A</code>" if hasattr(anime, "banner"): await m.reply_photo(photo=anime.banner, caption=text) else: await m.reply_text(text)
async def anime_view_description(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)) user_id = int(callback.matches[0].group(2)) page = int(callback.matches[0].group(3)) if user_id != user.id: return async with anilist.AsyncClient() as client: anime = await client.get(anime_id, "anime") description = anime.description amount = 1024 page = 1 if page <= 0 else page offset = (page - 1) * amount stop = offset + amount pages = math.ceil(len(description) / amount) description = description[offset - (3 if page > 1 else 0):stop] page_buttons = [] if page > 1: page_buttons.append( ("⬅️", f"anime description {anime_id} {user_id} {page - 1}")) if not page == pages: description = description[:len(description) - 3] + "..." page_buttons.append( ("➡️", f"anime description {anime_id} {user_id} {page + 1}")) keyboard = [] if len(page_buttons) > 0: keyboard.append(page_buttons) keyboard.append([(lang.back_button, f"anime more {anime_id} {user_id}") ]) await message.edit_text( description, reply_markup=ikb(keyboard), )
async def anime_view(bot: Amime, union: Union[CallbackQuery, Message]): is_callback = isinstance(union, CallbackQuery) message = union.message if is_callback else union chat = message.chat user = union.from_user lang = union._lang is_private = await filters.private(bot, message) is_collaborator = await filters.collaborator( bot, union) or await filters.sudo(bot, union) query = union.matches[0].group(1) if is_callback: user_id = union.matches[0].group(2) if user_id is not None: user_id = int(user_id) if user_id != user.id: return to_delete = union.matches[0].group(3) if bool(to_delete) and not is_private: await message.delete() if not bool(query): return async with anilist.AsyncClient() as client: if not query.isdecimal(): results = await client.search(query, "anime", 10) if results is None: await asyncio.sleep(0.5) results = await client.search(query, "anime", 10) if results is None: return if len(results) == 1: anime_id = results[0].id else: keyboard = [] for result in results: keyboard.append([(result.title.romaji, f"anime {result.id} {user.id} 1")]) await message.reply_text( lang.search_results_text(query=query, ), reply_markup=ikb(keyboard), ) return else: anime_id = int(query) anime = await client.get(anime_id, "anime") if anime is None: return user_db = await Users.get(id=user.id) language = user_db.language_anime episodes = await Episodes.filter(anime=anime.id) episodes = sorted(episodes, key=lambda episode: episode.number) episodes = [ *filter(lambda episode: len(episode.file_id) > 0, episodes) ] text = f"<b>{anime.title.romaji}</b>" if hasattr(anime.title, "native"): text += f" (<code>{anime.title.native}</code>)" text += f"\n\n<b>ID</b>: <code>{anime.id}</code>" if hasattr(anime, "score"): if hasattr(anime.score, "average"): text += f"\n<b>{lang.score}</b>: <code>{anime.score.average}</code>" text += f"\n<b>{lang.status}</b>: <code>{anime.status}</code>" if hasattr(anime, "genres"): text += f"\n<b>{lang.genres}</b>: <code>{', '.join(anime.genres)}</code>" if hasattr(anime, "studios"): text += f"\n<b>{lang.studios}</b>: <code>{', '.join(anime.studios)}</code>" text += f"\n<b>{lang.format}</b>: <code>{anime.format}</code>" if hasattr(anime, "duration"): text += f"\n<b>{lang.duration}</b>: <code>{anime.duration}m</code>" if not anime.format.lower() == "movie" and hasattr(anime, "episodes"): text += f"\n<b>{lang.episode}s</b>: <code>{anime.episodes}</code>" if not anime.status.lower() == "not_yet_released": text += f"\n<b>{lang.start_date}</b>: <code>{anime.start_date.day if hasattr(anime.start_date, 'day') else 0}/{anime.start_date.month if hasattr(anime.start_date, 'month') else 0}/{anime.start_date.year if hasattr(anime.start_date, 'year') else 0}</code>" if not anime.status.lower() in ["not_yet_released", "releasing"]: text += f"\n<b>{lang.end_date}</b>: <code>{anime.end_date.day if hasattr(anime.end_date, 'day') else 0}/{anime.end_date.month if hasattr(anime.end_date, 'month') else 0}/{anime.end_date.year if hasattr(anime.end_date, 'year') else 0}</code>" buttons = [ (lang.view_more_button, f"anime more {anime.id} {user.id}"), ] if is_private: buttons.append(await get_favorite_button(lang, user, "anime", anime.id)) if len(episodes) > 0: if is_private: if anime.format.lower() == "movie": buttons.append( (lang.watch_button, f"episode {anime.id} 0 1")) else: buttons.append(( lang.watch_button, f"episodes {anime.id} {episodes[0].season} 1", )) else: buttons.append(( lang.watch_button, f"https://t.me/{bot.me.username}/?start=anime_{anime.id}", "url", )) buttons.append(await get_notify_button(lang, user if is_private else chat, "anime", anime.id)) if is_private and is_collaborator: buttons.append(( lang.manage_button, f"manage anime {anime.id} 0 1 {language} 1", )) if is_private and not anime.status.lower() == "not_yet_released": button = ( lang.request_content_button, f"request episodes {anime.id} {language}", ) if anime.status.lower() == "releasing": if hasattr(anime, "next_airing"): next_episode = anime.next_airing.episode if len(episodes) < (next_episode - 1): buttons.append(button) else: buttons.append(button) elif hasattr(anime, "episodes"): if len(episodes) < anime.episodes: buttons.append(button) keyboard = array_chunk(buttons, 2) photo = f"https://img.anili.st/media/{anime.id}" if bool(message.video) and is_callback: await union.edit_message_media( InputMediaPhoto( photo, caption=text, ), reply_markup=ikb(keyboard), ) elif bool(message.photo) and not bool(message.via_bot): await message.edit_text( text, reply_markup=ikb(keyboard), ) else: await message.reply_photo( photo, caption=text, reply_markup=ikb(keyboard), )
async def test_search(query, content_type): client = anilist.AsyncClient() assert await client.search(query, content_type, pagination=True) is not None assert await client.search(query, content_type, pagination=False) is not None
async def anime_episode(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)) number = int(callback.matches[0].group(3)) async with anilist.AsyncClient() as client: anime = await client.get(anime_id, "anime") if anime is None: return text = f"<b>{anime.title.romaji}</b> (<code>{anime.title.native}</code>)\n" user_db = await Users.get(id=user.id) language = user_db.language_anime subtitled = user_db.subtitled_anime episodes = await Episodes.filter(anime=anime_id, season=season, language=language, subtitled=subtitled) episodes = sorted(episodes, key=lambda episode: episode.number) all_episodes = await Episodes.filter(anime=anime_id, language=language, subtitled=subtitled) all_episodes = sorted(all_episodes, key=lambda episode: episode.number) episode = await Episodes.get_or_none( anime=anime_id, season=season, number=number, language=language, subtitled=subtitled, ) if episode is not None: await Viewed.get_or_create(user=user.id, item=episode.id, type="anime") keyboard = [[await get_watched_button(lang, user, episode.id)]] if len(episode.name) > 0: text += f"\n<b>{lang.name}</b>: <code>{episode.name}</code>" if episode.season > 0: text += f"\n<b>{lang.season}</b>: <code>{episode.season}</code>" episode_number = f"{episode.number}" if episode.unified_until > 0: episode_number += f"-{episode.unified_until}" text += f"\n<b>{lang.episode}</b>: <code>{episode_number}</code>" text += f"\n<b>{lang.duration}</b>: <code>{episode.duration}m</code>" text += f"\n<b>{lang.language}</b>: <code>{lang.strings[episode.language]['LANGUAGE_NAME']}</code>" if len(episode.added_by) > 0: if not episode.added_by.isdecimal(): text += f"\n<b>{lang.added_by}</b>: <b>{episode.added_by}</b>" if len(episode.notes) > 0: text += f"\n<b>{lang.notes}</b>: <i>{episode.notes}</i>" viewed = await Viewed.filter(item=episode.id, type="anime") text += f"\n\n<b>{len(viewed)} {lang.views.lower()}</b>" previous_button = await get_previous_episode_button( lang, episodes, all_episodes, anime_id, season, number, language) next_button = await get_next_episode_button( lang, episodes, all_episodes, anime_id, season, number) if not (previous_button[0] == lang.dot_button and next_button[0] == lang.dot_button): keyboard.append([previous_button, next_button]) keyboard.append([( lang.report_button, f"report episode {anime_id} {season} {number} -1", )]) if anime.format.lower() == "movie": keyboard.append([( lang.back_button, f"anime {anime_id} {user.id}", )]) else: keyboard.append([( lang.back_button, f"episodes {anime_id} {season} {math.ceil(number / (5 * 3))}", )]) await callback.edit_message_media( InputMediaVideo( episode.file_id, caption=text, ), reply_markup=ikb(keyboard), )
async def anilist_anime(c: Korone, m: Message): query = m.matches[0]["search"] if query.isdecimal(): anime_id = int(query) else: try: async with anilist.AsyncClient() as client: results = await client.search(query, "anime", page=1, limit=1) anime_id = results[0].id except IndexError: return await m.reply_text( "Algo deu errado, verifique sua pesquisa e tente novamente!" ) async with anilist.AsyncClient() as client: anime = await client.get(anime_id) if not anime: return await m.reply_text( f"Desculpe! Nenhum <b>anime</b> com o ID <code>{anime_id}</code> foi encontrado..." ) if hasattr(anime, "description"): if len(anime.description) > 700: desc = f"<b>Descrição curta:</b> <i>{anime.description_short}</i>[...]" else: desc = f"<b>Descrição:</b> <i>{anime.description}</i>" text = f"<b>{anime.title.romaji}</b> {f'(<code>{anime.title.native}</code>)' if hasattr(anime.title, 'native') else ''}\n" text += f"<b>ID:</b> <code>{anime.id}</code>\n" text += f"<b>Tipo:</b> <code>{anime.format}</code>\n" if hasattr(anime, "status"): text += f"<b>Estado:</b> <code>{anime.status}</code>\n" if hasattr(anime, "episodes"): text += f"<b>Episódios:</b> <code>{anime.episodes}</code>\n" if hasattr(anime, "duration"): text += f"<b>Duração:</b> <code>{anime.duration}</code> Por Ep.\n" if hasattr(anime.score, "average"): text += f"<b>Pontuação:</b> <code>{anime.score.average}</code>\n" if hasattr(anime, "genres"): text += ( f"<b>Gêneros:</b> <code>{', '.join(str(x) for x in anime.genres)}</code>\n" ) if hasattr(anime, "studios"): text += f"<b>Estúdios:</b> <code>{', '.join(str(x) for x in anime.studios)}</code>\n" if anime.status.lower() != "not_yet_released": text += f"<b>Inicio:</b> <code>{anime.start_date.day if hasattr(anime.start_date, 'day') else 0}/{anime.start_date.month if hasattr(anime.start_date, 'month') else 0}/{anime.start_date.year if hasattr(anime.start_date, 'year') else 0}</code>\n" if anime.status.lower() not in ["not_yet_released", "releasing"]: text += f"<b>Finalização:</b> <code>{anime.end_date.day if hasattr(anime.end_date, 'day') else 0}/{anime.end_date.month if hasattr(anime.end_date, 'month') else 0}/{anime.end_date.year if hasattr(anime.end_date, 'year') else 0}</code>\n" if hasattr(anime, "description"): text += f"\n{desc}" keyboard = [[("Mais informações", anime.url, "url")]] if hasattr(anime, "trailer"): keyboard[0].append(("Trailer 🎬", anime.trailer.url, "url")) await m.reply_photo( photo=f"https://img.anili.st/media/{anime.id}", caption=text, reply_markup=c.ikb(keyboard), )
async def inline_manga(c: Korone, q: InlineQuery): results: List[InlineQueryResultPhoto] = [] query = q.query.split() if len(query) != 0 and query[0] == "manga": search = " ".join(query[1:]) async with anilist.AsyncClient() as client: results_search = await client.search(search, "manga", page=1, limit=10) for result in results_search: manga = await client.get(result.id, "manga") if hasattr(manga, "description"): if len(manga.description) > 700: desc = f"<b>Descrição curta:</b> <i>{manga.description_short}</i>[...]" else: desc = f"<b>Descrição:</b> <i>{manga.description}</i>" text = f"<b>{manga.title.romaji}</b> {f'(<code>{manga.title.native}</code>)' if hasattr(manga.title, 'native') else ''}\n" text += f"<b>ID:</b> <code>{manga.id}</code>\n" if hasattr(manga, "status"): text += f"<b>Estado:</b> <code>{manga.status}</code>\n" if hasattr(manga, "chapters"): text += f"<b>Capítulos:</b> <code>{manga.chapters}</code>\n" if hasattr(manga, "volumes"): text += f"<b>Volumes:</b> <code>{manga.volumes}</code>\n" if hasattr(manga.score, "average"): text += f"<b>Pontuação:</b> <code>{manga.score.average}</code>\n" if hasattr(manga, "genres"): text += f"<b>Gêneros:</b> <code>{', '.join(str(x) for x in manga.genres)}</code>\n" if not manga.status.lower() == "not_yet_released": text += f"<b>Início:</b> <code>{manga.start_date.day if hasattr(manga.start_date, 'day') else 0}/{manga.start_date.month if hasattr(manga.start_date, 'month') else 0}/{manga.start_date.year if hasattr(manga.start_date, 'year') else 0}</code>\n" if not manga.status.lower() in [ "not_yet_released", "releasing", ]: text += f"<b>Finalização:</b> <code>{manga.end_date.day if hasattr(manga.end_date, 'day') else 0}/{manga.end_date.month if hasattr(manga.end_date, 'month') else 0}/{manga.end_date.year if hasattr(manga.end_date, 'year') else 0}</code>\n" if hasattr(manga, "description"): text += f"\n{desc}" keyboard = [ [ ("Mais Info", manga.url, "url"), ( "Pesquisar mais", "manga", "switch_inline_query_current_chat", ), ] ] photo = f"https://img.anili.st/media/{manga.id}" results.append( InlineQueryResultPhoto( photo_url=photo, title=manga.title.romaji, description=cleanhtml(desc), caption=text, reply_markup=c.ikb(keyboard), ) ) try: if len(results) > 0: await q.answer( results=results, cache_time=0, ) except QueryIdInvalid: pass
async def anime_episode(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)) 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)) if str(user.id) not in EPISODES.keys(): EPISODES[str(user.id)] = {} if str(anime_id) not in EPISODES[str(user.id)].keys(): EPISODES[str(user.id)][str(anime_id)] = {} chat.cancel_listener() episode = EPISODES[str(user.id)][str(anime_id)] episode_db = await Episodes.get_or_none( anime=anime_id, season=season, number=number, language=language, subtitled=subtitled, ) if episode_db is not None: if not ("id" in episode.keys() and episode["id"] == episode_db.id): episode["id"] = episode_db.id episode["video"] = episode_db.file_id episode["name"] = episode_db.name episode["notes"] = episode_db.notes episode["duration"] = episode_db.duration episode["unified_until"] = episode_db.unified_until EPISODES[str(user.id)][str(anime_id)] = episode elif number == -1: EPISODES[str(user.id)][str(anime_id)] = {} episode = EPISODES[str(user.id)][str(anime_id)] episodes = await Episodes.filter( anime=anime_id, season=season, language=language, subtitled=subtitled, ) episodes = sorted(episodes, key=lambda episode: episode.number) if len(episodes) > 0: number = episodes[-1].number + 1 else: number = 1 episode["subtitled"] = subtitled async with anilist.AsyncClient() as client: anime = await client.get(anime_id, "anime") if anime is None: return logger.debug( "%s is editing/adding episode %s of the anime %s (%s)", user.first_name, number, anime_id, language, ) text = lang.manage_episode_text text += f"\n<b>{anime.title.romaji}</b> (<code>{anime.title.native}</code>)\n" buttons = [] if "name" in episode.keys() and len(episode["name"]) > 0: text += f"\n<b>{lang.name}</b>: <code>{episode['name']}</code>" buttons.append(( f"✏️ {lang.name}", f"manage episode edit name {anime_id} {season} {number} {int(subtitled)} {language} {page}", )) else: buttons.append(( f"➕ {lang.name}", f"manage episode edit name {anime_id} {season} {number} {int(subtitled)} {language} {page}", )) if season > 0: text += f"\n<b>{lang.season}</b>: <code>{season}</code>" if number != -1: episode_number = str(number) if "unified_until" in episode.keys() and int( episode["unified_until"]) > 0: episode_number += f"-{episode['unified_until']}" text += f"\n<b>{lang.episode}</b>: <code>{episode_number}</code>" buttons.append(( f"✏️ {lang.episode}", f"manage episode edit number {anime_id} {season} {number} {int(subtitled)} {language} {page}", )) else: buttons.append(( f"➕ {lang.episode}", f"manage episode edit number {anime_id} {season} {number} {int(subtitled)} {language} {page}", )) if "video" in episode.keys(): buttons.append(( f"✏️ {lang.video}", f"manage episode edit video {anime_id} {season} {number} {int(subtitled)} {language} {page}", )) else: buttons.append(( f"➕ {lang.video}", f"manage episode edit video {anime_id} {season} {number} {int(subtitled)} {language} {page}", )) if "duration" in episode.keys(): text += f"\n<b>{lang.duration}</b>: <code>{episode['duration']}m</code>" buttons.append(( f"✏️ {lang.duration}", f"manage episode edit duration {anime_id} {season} {number} {int(subtitled)} {language} {page}", )) else: buttons.append(( f"➕ {lang.duration}", f"manage episode edit duration {anime_id} {season} {number} {int(subtitled)} {language} {page}", )) text += f"\n<b>{lang.language}</b>: <code>{lang.strings[language]['LANGUAGE_NAME']}</code>" if "notes" in episode.keys() and len(episode["notes"]) > 0: text += f"\n<b>{lang.notes}</b>: <i>{episode['notes']}</i>" buttons.append(( f"✏️ {lang.notes}", f"manage episode edit notes {anime_id} {season} {number} {int(subtitled)} {language} {page}", )) else: buttons.append(( f"➕ {lang.notes}", f"manage episode edit notes {anime_id} {season} {number} {int(subtitled)} {language} {page}", )) keyboard = array_chunk(buttons, 2) buttons = [] if number != -1 and "video" in episode.keys(): episode["number"] = number buttons.append(( lang.confirm_button, f"manage episode save {anime_id} {season} {int(subtitled)} {language} {page}", )) if "id" in episode.keys(): buttons.append(( lang.del_button, f"manage episode delete {anime_id} {season} {number} {int(subtitled)} {language} {page}", )) buttons.append(( lang.back_button, f"manage anime {anime_id} {season} {int(subtitled)} {language} {page}", )) keyboard += array_chunk(buttons, 2) if "video" in episode.keys(): file_id = False if isinstance(episode["video"], str) and len(episode["video"]) > 0: file_id = episode["video"] elif isinstance(episode["video"], Video): file_id = episode["video"].file_id if file_id is not False: try: await callback.edit_message_media( InputMediaVideo( file_id, caption=text, ), reply_markup=ikb(keyboard), ) return except BaseException: pass await callback.edit_message_media( InputMediaPhoto( f"https://img.anili.st/media/{anime_id}", caption=text, ), reply_markup=ikb(keyboard), )
async def test_get_list_item(): client = anilist.AsyncClient() assert await client.get_list_item("travis", "5081") is not None assert await client.get_list_item("travis", "72451") is not None
async def anime_inline(bot: Amime, inline_query: InlineQuery): query = inline_query.matches[0]["query"].strip() lang = inline_query._lang if query.startswith("!"): inline_query.continue_propagation() results: List[InlineQueryResultPhoto] = [] async with anilist.AsyncClient() as client: search_results = await client.search(query, "anime", 15) while search_results is None: search_results = await client.search(query, "anime", 10) await asyncio.sleep(5) for result in search_results: anime = await client.get(result.id, "anime") if anime is None: continue photo: str = "" if hasattr(anime, "banner"): photo = anime.banner elif hasattr(anime, "cover"): if hasattr(anime.cover, "extra_large"): photo = anime.cover.extra_large elif hasattr(anime.cover, "large"): photo = anime.cover.large elif hasattr(anime.cover, "medium"): photo = anime.cover.medium description: str = "" if hasattr(anime, "description"): description = anime.description description = re.sub(re.compile(r"<.*?>"), "", description) description = description[0:260] + "..." text = f"<b>{anime.title.romaji}</b>" if hasattr(anime.title, "native"): text += f" (<code>{anime.title.native}</code>)" text += f"\n\n<b>ID</b>: <code>{anime.id}</code> (<b>ANIME</b>)" if hasattr(anime, "score"): if hasattr(anime.score, "average"): text += f"\n<b>{lang.score}</b>: <code>{anime.score.average}</code>" text += f"\n<b>{lang.status}</b>: <code>{anime.status}</code>" if hasattr(anime, "genres"): text += ( f"\n<b>{lang.genres}</b>: <code>{', '.join(anime.genres)}</code>" ) if hasattr(anime, "studios"): text += ( f"\n<b>{lang.studios}</b>: <code>{', '.join(anime.studios)}</code>" ) if hasattr(anime, "format"): text += f"\n<b>{lang.format}</b>: <code>{anime.format}</code>" if not anime.status.lower() == "not_yet_released": text += f"\n<b>{lang.start_date}</b>: <code>{anime.start_date.day if hasattr(anime.start_date, 'day') else 0}/{anime.start_date.month if hasattr(anime.start_date, 'month') else 0}/{anime.start_date.year if hasattr(anime.start_date, 'year') else 0}</code>" if not anime.status.lower() in ["not_yet_released", "releasing"]: text += f"\n<b>{lang.end_date}</b>: <code>{anime.end_date.day if hasattr(anime.end_date, 'day') else 0}/{anime.end_date.month if hasattr(anime.end_date, 'month') else 0}/{anime.end_date.year if hasattr(anime.end_date, 'year') else 0}</code>" text += f"\n\n<b>{lang.short_description}</b>: <i>{description}</i>" keyboard = [ [( lang.view_more_button, f"https://t.me/{bot.me.username}/?start=anime_{anime.id}", "url", )], ] results.append( InlineQueryResultPhoto( photo_url=photo, title=f"{anime.title.romaji} | {anime.format}", description=description, caption=text, reply_markup=ikb(keyboard), )) if len(results) > 0: try: await inline_query.answer( results=results, is_gallery=False, cache_time=3, ) except QueryIdInvalid: pass
async def character_view(bot: Amime, union: Union[CallbackQuery, Message]): is_callback = isinstance(union, CallbackQuery) message = union.message if is_callback else union user = union.from_user lang = union._lang is_private = await filters.private(bot, message) query = union.matches[0].group(1) if is_callback: user_id = union.matches[0].group(2) if user_id is not None: user_id = int(user_id) if user_id != user.id: return is_search = union.matches[0].group(3) if bool(is_search) and not is_private: await message.delete() if not bool(query): return async with anilist.AsyncClient() as client: if not query.isdecimal(): results = await client.search(query, "character", 10) if results is None: await asyncio.sleep(0.5) results = await client.search(query, "character", 10) if results is None: return if len(results) == 1: character_id = results[0].id else: keyboard = [] for result in results: keyboard.append( [(result.name.full, f"character {result.id} {user.id} 1")] ) await message.reply_text( lang.search_results_text( query=query, ), reply_markup=ikb(keyboard), ) return else: character_id = int(query) character = await client.get(character_id, "character") if character is None: return text = f"<b>{character.name.full}</b>" text += f"\n<b>ID</b>: <code>{character.id}</code>" if hasattr(character, "favorites"): text += f"\n<b>{lang.favorite}s</b>: <code>{character.favorites}</code>" text += f"\n\n{character.description}" photo: str = "" if hasattr(character, "image"): if hasattr(character.image, "large"): photo = character.image.large elif hasatrr(character.image, "medium"): photo = character.image.medium keyboard = [ [ ("🐢 Anilist", character.url, "url"), ], ] if len(text) > 1024: text = text[:1021] + "..." # Markdown text = text.replace("__", "**") text = text.replace("~", "~~") if len(photo) > 0: await message.reply_photo( photo, caption=text, parse_mode="combined", reply_markup=ikb(keyboard), ) else: await message.reply_text( text, parse_mode="combined", reply_markup=ikb(keyboard), )
async def inline_anime(c: Korone, q: InlineQuery): results: List[InlineQueryResultPhoto] = [] query = q.query.split() if len(query) != 0 and query[0] == "anime": search = " ".join(query[1:]) async with anilist.AsyncClient() as client: results_search = await client.search(search, "anime", page=1, limit=10) for result in results_search: anime = await client.get(result.id, "anime") if hasattr(anime, "description"): if len(anime.description) > 700: desc = f"<b>Descrição curta:</b> <i>{anime.description_short}</i>[...]" else: desc = f"<b>Descrição:</b> <i>{anime.description}</i>" text = f"<b>{anime.title.romaji}</b> {f'(<code>{anime.title.native}</code>)' if hasattr(anime.title, 'native') else ''}\n" text += f"<b>ID:</b> <code>{anime.id}</code>\n" text += f"<b>Tipo:</b> <code>{anime.format}</code>\n" if hasattr(anime, "status"): text += f"<b>Estado:</b> <code>{anime.status}</code>\n" if hasattr(anime, "episodes"): text += f"<b>Episódios:</b> <code>{anime.episodes}</code>\n" if hasattr(anime, "duration"): text += f"<b>Duração:</b> <code>{anime.duration}</code> Por Ep.\n" if hasattr(anime.score, "average"): text += f"<b>Pontuação:</b> <code>{anime.score.average}</code>\n" if hasattr(anime, "genres"): text += f"<b>Gêneros:</b> <code>{', '.join(str(x) for x in anime.genres)}</code>\n" if hasattr(anime, "studios"): text += f"<b>Estúdios:</b> <code>{', '.join(str(x) for x in anime.studios)}</code>\n" if not anime.status.lower() == "not_yet_released": text += f"<b>Inicio:</b> <code>{anime.start_date.day if hasattr(anime.start_date, 'day') else 0}/{anime.start_date.month if hasattr(anime.start_date, 'month') else 0}/{anime.start_date.year if hasattr(anime.start_date, 'year') else 0}</code>\n" if not anime.status.lower() in [ "not_yet_released", "releasing", ]: text += f"<b>Finalização:</b> <code>{anime.end_date.day if hasattr(anime.end_date, 'day') else 0}/{anime.end_date.month if hasattr(anime.end_date, 'month') else 0}/{anime.end_date.year if hasattr(anime.end_date, 'year') else 0}</code>\n" if hasattr(anime, "description"): text += f"\n{desc}" keyboard = [[("Mais informações", anime.url, "url")]] if hasattr(anime, "trailer"): keyboard[0].append(("Trailer 🎬", anime.trailer.url, "url")) keyboard.append( [ ( "Pesquisar mais", "anime", "switch_inline_query_current_chat", ) ] ) title = f"{anime.title.romaji} | {anime.format}" photo = f"https://img.anili.st/media/{anime.id}" results.append( InlineQueryResultPhoto( photo_url=photo, title=title, description=cleanhtml(desc), caption=text, reply_markup=c.ikb(keyboard), ) ) try: if len(results) > 0: await q.answer( results=results, cache_time=0, ) except QueryIdInvalid: pass
async def manga_view(bot: Amime, union: Union[CallbackQuery, Message]): is_callback = isinstance(union, CallbackQuery) message = union.message if is_callback else union chat = message.chat user = union.from_user lang = union._lang is_private = await filters.private(bot, message) query = union.matches[0].group(1) if is_callback: user_id = union.matches[0].group(2) if user_id is not None: user_id = int(user_id) if user_id != user.id: return is_search = union.matches[0].group(3) if bool(is_search) and not is_private: await message.delete() if not bool(query): return async with anilist.AsyncClient() as client: if not query.isdecimal(): results = await client.search(query, "manga", 10) if results is None: await asyncio.sleep(0.5) results = await client.search(query, "manga", 10) if results is None: return if len(results) == 1: manga_id = results[0].id else: keyboard = [] for result in results: keyboard.append([(result.title.romaji, f"manga {result.id} {user.id} 1")]) await message.reply_text( lang.search_results_text(query=query, ), reply_markup=ikb(keyboard), ) return else: manga_id = int(query) manga = await client.get(manga_id, "manga") if manga is None: return photo: str = "" if hasattr(manga, "banner"): photo = manga.banner elif hasattr(manga, "cover"): if hasattr(manga.cover, "extra_large"): photo = manga.cover.extra_large elif hasattr(manga.cover, "large"): photo = manga.cover.large elif hasattr(manga.cover, "medium"): photo = manga.cover.medium text = f"<b>{manga.title.romaji}</b>" if hasattr(manga.title, "native"): text += f" (<code>{manga.title.native}</code>)" text += f"\n\n<b>ID</b>: <code>{manga.id}</code>" if hasattr(manga, "score"): if hasattr(manga.score, "average"): text += f"\n<b>{lang.score}</b>: <code>{manga.score.average}</code>" text += f"\n<b>{lang.status}</b>: <code>{manga.status}</code>" if hasattr(manga, "genres"): text += f"\n<b>{lang.genres}</b>: <code>{', '.join(manga.genres)}</code>" if hasattr(manga, "volumes"): text += f"\n<b>{lang.volume}s</b>: <code>{manga.volumes}</code>" if hasattr(manga, "chapters"): text += f"\n<b>{lang.chapter}s</b>: <code>{manga.chapters}</code>" if not manga.status.lower() == "not_yet_released": text += f"\n<b>{lang.start_date}</b>: <code>{manga.start_date.day if hasattr(manga.start_date, 'day') else 0}/{manga.start_date.month if hasattr(manga.start_date, 'month') else 0}/{manga.start_date.year if hasattr(manga.start_date, 'year') else 0}</code>" if not manga.status.lower() in ["not_yet_released", "releasing"]: text += f"\n<b>{lang.end_date}</b>: <code>{manga.end_date.day if hasattr(manga.end_date, 'day') else 0}/{manga.end_date.month if hasattr(manga.end_date, 'month') else 0}/{manga.end_date.year if hasattr(manga.end_date, 'year') else 0}</code>" buttons = [ (lang.view_more_button, f"manga more {manga.id} {user.id}"), ] if is_private: buttons.append(await get_favorite_button(lang, user, "manga", manga.id)) buttons.append(await get_notify_button(lang, user if is_private else chat, "manga", manga.id)) keyboard = array_chunk(buttons, 2) if bool(message.photo) and not bool(message.via_bot): await message.edit_text( text, reply_markup=ikb(keyboard), ) else: await message.reply_photo( photo, caption=text, reply_markup=ikb(keyboard), )
async def anilist_anime(message, strings): query = get_args_str(message) if query.isdecimal(): anime_id = int(query) else: try: async with anilist.AsyncClient() as client: results = await client.search(query, "anime", 1) anime_id = results[0].id except IndexError: return await message.reply(strings["search_err"]) async with anilist.AsyncClient() as client: anime = await client.get(anime_id) if not anime: return await message.reply(strings["search_get_err"].format( type="anime", id=anime_id)) if hasattr(anime, "description"): if len(anime.description) > 700: desc = strings["short_desc"].format(desc=anime.description_short) else: desc = strings["desc"].format(desc=anime.description) text = f"<b>{anime.title.romaji}</b> (<code>{anime.title.native}</code>)" text += strings["id"].format(id=anime.id) text += strings["anime_type"].format(type=anime.format) if hasattr(anime, "status"): text += strings["status"].format(status=anime.status) if hasattr(anime, "episodes"): text += strings["anime_episodes"].format(ep=anime.episodes) if hasattr(anime, "duration"): text += strings["anime_duration"].format(time=anime.duration) if hasattr(anime.score, "average"): text += strings["score"].format(score=anime.score.average) if hasattr(anime, "genres"): text += strings["genres"].format( genres=f" <code>{', '.join(str(x) for x in anime.genres)}</code>\n" ) if hasattr(anime, "studios"): text += strings["anime_studios"].format( studios= f" <code>{', '.join(str(x) for x in anime.studios)}</code>\n") if hasattr(anime, "description"): text += f"\n{desc.replace('<br>', '')}" keyboard = InlineKeyboardMarkup().add( InlineKeyboardButton(text=strings["more_info"], url=anime.url)) try: keyboard.insert( InlineKeyboardButton(text=strings["trailer"] + " 🎬", url=anime.trailer.url)) except BaseException: pass await message.reply_photo( photo=f"https://img.anili.st/media/{anime.id}", caption=text, reply_markup=keyboard, )
async def character_inline(bot: Amime, inline_query: InlineQuery): query = inline_query.matches[0]["query"].strip() lang = inline_query._lang results: List[InlineQueryResultPhoto] = [] async with anilist.AsyncClient() as client: search_results = await client.search(query, "character", 15) while search_results is None: search_results = await client.search(query, "character", 10) await asyncio.sleep(5) for result in search_results: character = await client.get(result.id, "character") if character is None: continue photo: str = "" if hasattr(character, "image"): if hasattr(character.image, "large"): photo = character.image.large elif hasatrr(character.image, "medium"): photo = character.image.medium description: str = "" if hasattr(character, "description"): description = character.description description = description.replace("__", "") description = description.replace("**", "") description = description.replace("~", "") description = re.sub(re.compile(r"<.*?>"), "", description) description = description[0:260] + "..." text = f"<b>{character.name.full}</b>" text += f"\n<b>ID</b>: <code>{character.id}</code> (<b>CHARACTER</b>)" if hasattr(character, "favorites"): text += f"\n<b>{lang.favorite}s</b>: <code>{character.favorites}</code>" text += f"\n\n{description}" keyboard = [ [( lang.view_more_button, f"https://t.me/{bot.me.username}/?start=character_{character.id}", "url", )], ] results.append( InlineQueryResultPhoto( photo_url=photo, title=character.name.full, description=description, caption=text, reply_markup=ikb(keyboard), )) if len(results) > 0: try: await inline_query.answer( results=results, is_gallery=False, cache_time=3, ) except QueryIdInvalid: pass