├── .gitignore ├── LICENSE ├── README.md ├── bot.py ├── config.py ├── requirements.txt └── src ├── airing.py ├── anime_search.py ├── dev_info.py ├── genre_results.py ├── genres.py ├── get_anime_details.py ├── get_ep_numbers.py ├── get_episode_link.py ├── get_episodes_index.py ├── inline_search.py ├── inline_search_results.py ├── instructions.py └── start_message.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 BaraniARR 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Anime DL Telegram Bot 2 | 3 |
4 | Python 5 | PyCharm 6 | GitLab 7 | Git 8 |
9 | 10 |
11 | telegram 12 | Heroku 13 | Redis 14 |
15 | 16 |
17 | license 18 |
19 | 20 | An advanced telegram bot to get anime download links. 21 | 22 | ### How to deploy your own Anime DL Bot. 23 | ### 24 | ##### 1. Get your api_id and api_hash from [Telegram](telegram.org). 25 | ##### 2. Get your telegram bot token from [@botfather](https://t.me/botfather) 26 | ##### 3. Place the credentials in config.py 27 | ##### 4. Install the requirements using pip. 28 | 29 | ``` 30 | $ pip3 install -r requirements.txt 31 | ``` 32 | ### 33 | ##### 5. Run your bot by the following command 34 | 35 | ``` 36 | $ python3 bot.py 37 | ``` 38 | ### 39 | #### Star and Fork the Repo if you like it 💖💖 40 | ## Copyrights © 2021 BaraniARR 41 | -------------------------------------------------------------------------------- /bot.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2021 BaraniARR 2 | # Encoding = 'utf-8' 3 | # Licensed under MIT License 4 | # Special Thanks for gogoanime 5 | 6 | from pyrogram import * 7 | from pyrogram.handlers import * 8 | from src.anime_search import anime_search 9 | from src.start_message import start_message 10 | from src.dev_info import dev_info 11 | import logging 12 | from src.genres import genres 13 | from src.genre_results import genre_results 14 | from src.get_anime_details import anime_details 15 | from src.inline_search import inline_search 16 | from src.get_episodes_index import get_epIndex 17 | from src.get_episode_link import get_ep_link 18 | from src.instructions import instructions 19 | from src.airing import airing_eps 20 | from src.inline_search_results import anime_inline_details 21 | from src.get_ep_numbers import get_ep 22 | import config 23 | 24 | # Logging is optional 25 | logging.basicConfig( 26 | format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO 27 | ) 28 | logger = logging.getLogger(__name__) 29 | 30 | # Creating a Session to activate all Handlers 31 | bot = Client( 32 | "YOUR_SESSION_NAME", 33 | api_id=config.api_id, 34 | api_hash=config.api_hash, 35 | bot_token=config.bot_token 36 | ) 37 | 38 | # Adding all functions to Handlers in main() function 39 | def main(): 40 | bot.add_handler(MessageHandler(anime_search, filters.regex(r'search')), group=1) 41 | bot.add_handler(MessageHandler(start_message, filters.command('start')), group=2) 42 | bot.add_handler(MessageHandler(dev_info, filters.command('info')), group=3) 43 | bot.add_handler(MessageHandler(genres, filters.command('genres')), group=4) 44 | bot.add_handler(InlineQueryHandler(inline_search), group=6) 45 | bot.add_handler(MessageHandler(airing_eps, filters.command("airing")), group=7) 46 | bot.add_handler(CallbackQueryHandler(anime_details, filters.regex('dt_*')), group=8) 47 | bot.add_handler(CallbackQueryHandler(get_epIndex, filters.regex('dl_*')), group=9) 48 | bot.add_handler(CallbackQueryHandler(get_ep_link, filters.regex('eps_*')), group=10) 49 | bot.add_handler(CallbackQueryHandler(genre_results, filters.regex('genre/')), group=11) 50 | bot.add_handler(CallbackQueryHandler(instructions, filters.regex('instructions')), group=12) 51 | bot.add_handler(MessageHandler(anime_inline_details, filters.text), group=13) 52 | bot.add_handler(CallbackQueryHandler(get_ep, filters.regex('eplink_*')), group=14) 53 | 54 | # Calling main method and handlers, polling state 55 | if __name__ == '__main__': 56 | bot.run(main()) -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2021 BaraniARR 2 | # Encoding = 'utf-8' 3 | # Licensed under MIT License 4 | # Special Thanks for gogoanime 5 | 6 | """ANIME DL TELEGRAM BOT CREDENTIALS""" 7 | 8 | api_id = "" 9 | api_hash = "" 10 | bot_token = "" 11 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pyrogram 2 | TgCrypto 3 | beautifulsoup4 4 | requests 5 | requests_html 6 | redis 7 | 8 | -------------------------------------------------------------------------------- /src/airing.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2021 BaraniARR 2 | # Encoding = 'utf-8' 3 | # Licensed under MIT License 4 | # Special Thanks for gogoanime 5 | 6 | from pyrogram import * 7 | from pyrogram.types import * 8 | import requests 9 | from requests_html import HTMLSession 10 | from bs4 import BeautifulSoup 11 | import sys 12 | 13 | # Getting currently airing Anime from the API 14 | # Returns an "Inline Keyboard List" of Currently airing Anime 15 | 16 | def airing_eps(client, message): 17 | url = f"https://gogoanime.ai/" 18 | session = HTMLSession() 19 | response = session.get(url) 20 | response_html = response.text 21 | soup = BeautifulSoup(response_html, 'html.parser') 22 | anime = soup.find("nav", {"class": "menu_series cron"}).find("ul") 23 | air = [] 24 | for link in anime.find_all('a'): 25 | airing_link = link.get('href') 26 | name = link.get('title') 27 | link = airing_link.split('/') 28 | lnk_final = link[2] 29 | res = sys.getsizeof(lnk_final) 30 | if int(res) > 64: 31 | pass 32 | else: 33 | air.append([InlineKeyboardButton(f"{name}", callback_data=f"dt_{lnk_final}")]) 34 | repl = InlineKeyboardMarkup(air) 35 | message.reply_text("**Currently Airing Anime: **", reply_markup=repl, parse_mode="markdown") -------------------------------------------------------------------------------- /src/anime_search.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2021 BaraniARR 2 | # Encoding = 'utf-8' 3 | # Licensed under MIT License 4 | # Special Thanks for gogoanime 5 | 6 | from pyrogram import * 7 | from pyrogram.types import * 8 | from requests_html import HTMLSession 9 | from bs4 import BeautifulSoup 10 | 11 | # Searching anime by regex pattern "/search Anime Name" 12 | 13 | def anime_search(client, message): 14 | q = message.text 15 | q1 = q.split() 16 | q1.remove(q1[0]) 17 | str = " " 18 | query = str.join(q1) 19 | if query == "": 20 | # If no query string is mentioned 21 | message.reply_animation("https://media.tenor.com/images/cfe564edcb140705ce45aeeca8183812/tenor.gif", 22 | caption=f"""**Your Query should be in This format:** 23 | 24 | `/search Name of the Anime you want to Search.`""", parse_mode="markdown") 25 | else: 26 | url = f"https://gogoanime.ai//search.html?keyword={query}" 27 | session = HTMLSession() 28 | response = session.get(url) 29 | response_html = response.text 30 | soup = BeautifulSoup(response_html, 'html.parser') 31 | animes = soup.find("ul", {"class": "items"}).find_all("li") 32 | # print(animes) 33 | keyb = [] 34 | for anime in animes: # For every anime found 35 | tit = anime.a["title"] 36 | urll = anime.a["href"] 37 | r = urll.split('/') 38 | # aAnimes.append({"title" : anime.a["title"] , "link" : "https://www2.gogoanime.sh{}".format(anime.a["href"])}) 39 | keyb.append([InlineKeyboardButton("{}".format(tit), callback_data="dt_{}".format(r[2]))]) 40 | if keyb == []: 41 | # If returned list is empty, Send the following message. 42 | message.reply_text("No results found, Check your Spelling and Search Again...") 43 | else: 44 | rep = InlineKeyboardMarkup(keyb) 45 | message.reply_text(text=f"Your Search results for **{query}**", reply_markup=rep, parse_mode="markdown") 46 | 47 | -------------------------------------------------------------------------------- /src/dev_info.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2021 BaraniARR 2 | # Encoding = 'utf-8' 3 | # Licensed under MIT License 4 | # Special Thanks for gogoanime 5 | 6 | from pyrogram import * 7 | from pyrogram.types import * 8 | 9 | # Dev Info is Completely Optional 10 | 11 | def dev_info(client, message): 12 | keyb = [ 13 | [InlineKeyboardButton("Rate me on BotsArchive", url="https://t.me/BotsArchive/1858")] 14 | ] 15 | reply_markup = InlineKeyboardMarkup(keyb) 16 | message.reply_text("""Made with ❤️ in 🇮🇳 by . 17 | 18 | Language: [Python3](https://www.python.org/) 19 | 20 | Bot Framework: [Pyrogram Asyncio](https://github.com/pyrogram/pyrogram) 21 | 22 | Server: 23 | 24 | Please share the bot if you like it 👍👍""", reply_markup=reply_markup, parse_mode="markdown") -------------------------------------------------------------------------------- /src/genre_results.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2021 BaraniARR 2 | # Encoding = 'utf-8' 3 | # Licensed under MIT License 4 | # Special Thanks for gogoanime 5 | 6 | from pyrogram import * 7 | from pyrogram.types import * 8 | import requests 9 | from bs4 import BeautifulSoup 10 | from pyrogram.errors.exceptions.bad_request_400 import ButtonDataInvalid 11 | import sys 12 | 13 | # Get Inline Keyboard List of Anime with the returned Genre Callback_Data 14 | 15 | def genre_results(client, callback_query): 16 | query = callback_query 17 | data = query.data 18 | data_pre = data.split("_") 19 | gen = data_pre[1].split("/") 20 | gen_name = gen[2] 21 | try: 22 | url = f"https://gogoanime.ai{data_pre[1]}?page={data_pre[0]}" 23 | response = requests.get(url) 24 | plainText = response.text 25 | soup = BeautifulSoup(plainText, "lxml") 26 | animes = soup.find("ul", {"class": "items"}).find_all("li") 27 | keybrd_genre_butt = [] 28 | for anime in animes: # For every anime found 29 | tit = anime.a["title"] 30 | urll = anime.a["href"] 31 | r = urll.split('/') 32 | res = sys.getsizeof(r[2]) 33 | if int(res) > 64: 34 | pass 35 | else: 36 | keybrd_genre_butt.append([(InlineKeyboardButton(tit, callback_data=f"dt_{r[2]}"))]) 37 | # n = 3 38 | # keybrd_genre_butt = [keybrd_genre_butts[i:i + n] for i in range(0, len(keybrd_genre_butts), n)] 39 | callback_query.answer("Fetching Genres...") 40 | keybrd_genre_butt.append([InlineKeyboardButton("Back", callback_data=f"{int(data_pre[0]) - 1}_{data_pre[1]}"), 41 | (InlineKeyboardButton(f"Page {data_pre[0]}", callback_data="none")), 42 | (InlineKeyboardButton("Next", callback_data=f"{int(data_pre[0]) + 1}_{data_pre[1]}"))]) 43 | reply_markup = InlineKeyboardMarkup(keybrd_genre_butt) 44 | query.edit_message_text(f"Anime under genre **{gen_name}**: ", reply_markup=reply_markup, parse_mode="markdown") 45 | except AttributeError: 46 | callback_query.answer("End of search Results...", show_alert=True) 47 | -------------------------------------------------------------------------------- /src/genres.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2021 BaraniARR 2 | # Encoding = 'utf-8' 3 | # Licensed under MIT License 4 | # Special Thanks for gogoanime 5 | 6 | from pyrogram import * 7 | from pyrogram.types import * 8 | import requests 9 | from bs4 import BeautifulSoup 10 | 11 | # Lists out all Genres and related anime as callback_data 12 | 13 | def genres(client, message): 14 | gen_keyb = [] 15 | animelink = 'https://gogoanime.ai/' 16 | response = requests.get(animelink) 17 | plainText = response.text 18 | soup = BeautifulSoup(plainText, "lxml") 19 | anime = soup.find("nav", {"class": "menu_series genre right"}).find("ul") 20 | for link in anime.find_all('a'): 21 | genre_link = link.get('href') 22 | # print(genre_link) 23 | name = genre_link.split('/') 24 | genre_name = name[2] 25 | gen_keyb.append((InlineKeyboardButton(genre_name, callback_data=f"1_{genre_link}"))) 26 | # print(gen_keyb) 27 | n = 2 28 | keybrd_genre_butt = [gen_keyb[i:i + n] for i in range(0, len(gen_keyb), n)] 29 | #print(keybrd_genre_butt) 30 | reply_markup = InlineKeyboardMarkup(keybrd_genre_butt) 31 | message.reply_text("Choose One Genre to See anime Related to: ", reply_markup=reply_markup, parse_mode="markdown") -------------------------------------------------------------------------------- /src/get_anime_details.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2021 BaraniARR 2 | # Encoding = 'utf-8' 3 | # Licensed under MIT License 4 | # Special Thanks for gogoanime 5 | 6 | from pyrogram import * 7 | from pyrogram.types import * 8 | import requests 9 | from bs4 import BeautifulSoup 10 | 11 | # Get anime Details on anime_search callback_data 12 | 13 | def anime_details(client, callback_query): 14 | global list_more_anime 15 | query = callback_query 16 | dt = query.data 17 | dt1 = dt.split("_") 18 | data = dt1[1] 19 | query.answer("Fetching Anime Details...") 20 | animelink = 'https://gogoanime.ai/category/{}'.format(data) 21 | response = requests.get(animelink) 22 | plainText = response.text 23 | soup = BeautifulSoup(plainText, "lxml") 24 | source_url = soup.find("div", {"class": "anime_info_body_bg"}).img 25 | # url of anime image 26 | imgg = source_url.get('src') 27 | # title name of the anime 28 | tit_url = soup.find("div", {"class": "anime_info_body_bg"}).h1.string 29 | lis = soup.find_all('p', {"class": "type"}) 30 | plot_sum = lis[1] 31 | pl = plot_sum.get_text().split(':') 32 | pl.remove(pl[0]) 33 | sum = "" 34 | plot_summary = sum.join(pl) 35 | type_of_show = lis[0].a['title'] 36 | ai = lis[2].find_all('a') # .find_all('title') 37 | # get list of genres by using genres variable 38 | genres = [] 39 | for link in ai: 40 | genres.append(link.get('title')) 41 | # get released year 42 | year = lis[3].get_text() 43 | # status completed or airing,,, 44 | status = lis[4].a.get_text() 45 | # other names 46 | oth_names = lis[5].get_text() 47 | lnk = soup.find(id="episode_page") 48 | source_url = lnk.find("li").a 49 | # ending ep no 50 | try: 51 | source_url = lnk.findAll("li") 52 | for link in source_url: 53 | list_more_anime = [] 54 | list_more_anime.append(link.a) 55 | ep_num = list_more_anime[0].get("ep_end") 56 | except: 57 | source_url = lnk.find("li").a 58 | ep_num = source_url.get("ep_end") 59 | kkeeyyb = [ 60 | [InlineKeyboardButton("Download for Free", callback_data=f"dl_{data}")], 61 | ] 62 | reply_markup = InlineKeyboardMarkup(kkeeyyb) 63 | query.edit_message_text(f"""[{tit_url}]({imgg}) 64 | 65 | **{tit_url} ({year})** 66 | 67 | **{oth_names}** 68 | 69 | **Type:** `{type_of_show}` 70 | 71 | **Status: **__{status}__ 72 | 73 | **Genres: **`{genres}` 74 | 75 | **Episodes: **__{ep_num}__ 76 | 77 | **Summary: **`{plot_summary}`""", reply_markup=reply_markup, parse_mode="markdown") -------------------------------------------------------------------------------- /src/get_ep_numbers.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2021 BaraniARR 2 | # Encoding = 'utf-8' 3 | # Licensed under MIT License 4 | # Special Thanks for gogoanime 5 | 6 | from pyrogram import * 7 | from pyrogram.types import * 8 | import requests 9 | from bs4 import BeautifulSoup 10 | 11 | # get episodes from specific range, specified in get_episodes_index 12 | 13 | def get_ep(client, callback_query): 14 | dataInitial = callback_query.data 15 | dataSplit = dataInitial.split("_") 16 | animeid = dataSplit[1] 17 | ep_index_num = dataSplit[2] 18 | global list_more_anime 19 | query = callback_query 20 | data = query.data 21 | query.answer("Fetching Episodes...") 22 | data_spl = data.split("_") 23 | # print(data_spl) 24 | animelink = f'https://gogoanime.ai/category/{data_spl[1]}' 25 | response = requests.get(animelink) 26 | plainText = response.text 27 | soup = BeautifulSoup(plainText, "lxml") 28 | tit_url = soup.find("div", {"class": "anime_info_body_bg"}).h1.string 29 | lnk = soup.find(id="episode_page") 30 | try: 31 | source_url = lnk.findAll("li") 32 | for link in source_url: 33 | list_more_anime = [] 34 | list_more_anime.append(link.a) 35 | ep_num_tot = list_more_anime[0].get("ep_end") 36 | ep_num_tot_range = int(ep_num_tot) + 1 37 | except: 38 | source_url = lnk.find("li").a 39 | ep_num_tot = source_url.get("ep_end") 40 | ep_num_tot_range = int(ep_num_tot) + 1 41 | listInitial = [] 42 | for i in range(1, ep_num_tot_range): 43 | listInitial.append(i) 44 | n = 40 45 | listOrganisedInitial = [listInitial[i:i + n] for i in range(0, len(listInitial), n)] 46 | keyb_eps = [] 47 | for i in listOrganisedInitial[int(ep_index_num)]: 48 | keyb_eps.append((InlineKeyboardButton(f'{i}', callback_data=f"eps_{i}_{animeid}"))) 49 | m=5 50 | keybrd_inline_butt = [keyb_eps[i:i + m] for i in range(0, len(keyb_eps), m)] 51 | keybrd_inline_butt.append([InlineKeyboardButton("◀️ Back", callback_data=f"dl_{animeid}")]) 52 | reply_markups = InlineKeyboardMarkup(keybrd_inline_butt) 53 | query.edit_message_reply_markup(reply_markup=reply_markups) -------------------------------------------------------------------------------- /src/get_episode_link.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2021 BaraniARR 2 | # Encoding = 'utf-8' 3 | # Licensed under MIT License 4 | # Special Thanks for gogoanime 5 | 6 | from pyrogram import * 7 | from pyrogram.types import * 8 | import requests 9 | from requests_html import HTMLSession 10 | from bs4 import BeautifulSoup 11 | 12 | # gets lists of Episdoes link when episode number and anime id is passed as callback_data 13 | 14 | def get_ep_link(client, callback_query): 15 | query = callback_query 16 | data = query.data 17 | query.answer(f"Please wait till I fetch Links...") 18 | data_spl_ep = data.split("_") 19 | ep_num_link_get = int(data_spl_ep[1]) 20 | data_spl_ep.remove(data_spl_ep[0]) 21 | data_spl_ep.remove(data_spl_ep[0]) 22 | str_qry = "" 23 | str_qry_final = str_qry.join(data_spl_ep) 24 | # print(str_qry_final) 25 | animelink = f'https://gogoanime.ai/category/{str_qry_final}' 26 | response = requests.get(animelink) 27 | plainText = response.text 28 | soup = BeautifulSoup(plainText, "lxml") 29 | lnk = soup.find(id="episode_page") 30 | source_url = lnk.find("li").a 31 | tit_url = soup.find("div", {"class": "anime_info_body_bg"}).h1.string 32 | # print(tit_url) 33 | ep_num_tot = source_url.get("ep_end") 34 | last_ep = int(ep_num_tot) 35 | # print(last_ep) 36 | # print(ep_num_link_get) 37 | episode = ep_num_link_get 38 | # print("Generating Links from", start, "to", end) 39 | animename = animelink.split("/") 40 | URL_PATTERN = 'https://gogoanime.ai/{}-episode-{}' 41 | url = URL_PATTERN.format(str_qry_final, ep_num_link_get) 42 | srcCode = requests.get(url) 43 | plainText = srcCode.text 44 | soup = BeautifulSoup(plainText, "lxml") 45 | source_url = soup.find("li", {"class": "dowloads"}).a 46 | vidstream_link = source_url.get('href') 47 | # print(vidstream_link) 48 | URL = vidstream_link 49 | dowCode = requests.get(URL) 50 | data = dowCode.text 51 | soup = BeautifulSoup(data, "lxml") 52 | try: 53 | dow_url1 = soup.findAll('div', {'class': 'dowload'})[0].find('a') 54 | except: 55 | pass 56 | try: 57 | dow_url2 = soup.findAll('div', {'class': 'dowload'})[1].find('a') 58 | except: 59 | pass 60 | try: 61 | dow_url3 = soup.findAll('div', {'class': 'dowload'})[2].find('a') 62 | except: 63 | pass 64 | try: 65 | dow_url4 = soup.findAll('div', {'class': 'dowload'})[3].find('a') 66 | except: 67 | pass 68 | try: 69 | dow_url5 = soup.findAll('div', {'class': 'dowload'})[4].find('a') 70 | except: 71 | pass 72 | try: 73 | dow_url6 = soup.findAll('div', {'class': 'dowload'})[5].find('a') 74 | except: 75 | pass 76 | try: 77 | dow_url7 = soup.findAll('div', {'class': 'dowload'})[6].find('a') 78 | except: 79 | pass 80 | 81 | try: 82 | downlink1 = dow_url1.get('href') 83 | except: 84 | pass 85 | try: 86 | downlink2 = dow_url2.get('href') 87 | except: 88 | pass 89 | try: 90 | downlink3 = dow_url3.get('href') 91 | except: 92 | pass 93 | try: 94 | downlink4 = dow_url4.get('href') 95 | except: 96 | pass 97 | try: 98 | downlink5 = dow_url5.get('href') 99 | except: 100 | pass 101 | try: 102 | downlink6 = dow_url6.get('href') 103 | except: 104 | pass 105 | try: 106 | downlink7 = dow_url7.get('href') 107 | except: 108 | pass 109 | 110 | try: 111 | str1 = dow_url1.string 112 | str_spl1 = str1.split() 113 | str_spl1.remove(str_spl1[0]) 114 | str_original_1 = "" 115 | quality_name1 = str_original_1.join(str_spl1) 116 | except: 117 | pass 118 | 119 | try: 120 | str2 = dow_url2.string 121 | str_spl2 = str2.split() 122 | str_spl2.remove(str_spl2[0]) 123 | str_original_2 = "" 124 | quality_name2 = str_original_2.join(str_spl2) 125 | except: 126 | pass 127 | 128 | try: 129 | str3 = dow_url3.string 130 | str_spl3 = str3.split() 131 | str_spl3.remove(str_spl3[0]) 132 | str_original_3 = "" 133 | quality_name3 = str_original_3.join(str_spl3) 134 | except: 135 | pass 136 | 137 | try: 138 | str4 = dow_url4.string 139 | str_spl4 = str4.split() 140 | str_spl4.remove(str_spl4[0]) 141 | str_original_4 = "" 142 | quality_name4 = str_original_4.join(str_spl4) 143 | except: 144 | pass 145 | 146 | try: 147 | str5 = dow_url5.string 148 | str_spl5 = str5.split() 149 | str_spl5.remove(str_spl5[0]) 150 | str_original_5 = "" 151 | quality_name5 = str_original_5.join(str_spl5) 152 | except: 153 | pass 154 | 155 | try: 156 | str6 = dow_url6.string 157 | str_spl6 = str6.split() 158 | str_spl6.remove(str_spl6[0]) 159 | str_original_6 = "" 160 | quality_name6 = str_original_6.join(str_spl6) 161 | except: 162 | pass 163 | 164 | try: 165 | str7 = dow_url7.string 166 | str_spl7 = str7.split() 167 | str_spl7.remove(str_spl7[0]) 168 | str_original_7 = "" 169 | quality_name7 = str_original_7.join(str_spl7) 170 | except: 171 | pass 172 | 173 | res_list = [] 174 | try: 175 | res_list.append({'num':f'{ep_num_link_get}','qual':f'{quality_name1}','lnk':f'{downlink1}'}) 176 | except: 177 | pass 178 | try: 179 | res_list.append({'num':f'{ep_num_link_get}','qual':f'{quality_name2}','lnk':f'{downlink2}'}) 180 | except: 181 | pass 182 | try: 183 | res_list.append({'num':f'{ep_num_link_get}','qual':f'{quality_name3}','lnk':f'{downlink3}'}) 184 | except: 185 | pass 186 | try: 187 | res_list.append({'num':f'{ep_num_link_get}','qual':f'{quality_name4}','lnk':f'{downlink4}'}) 188 | except: 189 | pass 190 | try: 191 | res_list.append({'num':f'{ep_num_link_get}','qual':f'{quality_name5}','lnk':f'{downlink5}'}) 192 | except: 193 | pass 194 | try: 195 | res_list.append({'num':f'{ep_num_link_get}','qual':f'{quality_name6}','lnk':f'{downlink6}'}) 196 | except: 197 | pass 198 | try: 199 | res_list.append({'num':f'{ep_num_link_get}','qual':f'{quality_name7}','lnk':f'{downlink7}'}) 200 | except: 201 | pass 202 | 203 | 204 | if ep_num_link_get == last_ep: 205 | key = [] 206 | for links in res_list: 207 | ep_number = links.get('num') 208 | quality = links.get('qual') 209 | download_links = links.get('lnk') 210 | key.append((InlineKeyboardButton(f"Ep{ep_number} {quality}", url=f"{download_links}"))) 211 | n = 3 212 | keys = [key[i:i + n] for i in range(0, len(key), n)] 213 | keys.append([(InlineKeyboardButton("⏪ Previous Ep", callback_data=f"eps_{ep_num_link_get - 1}_{str_qry_final}")), 214 | (InlineKeyboardButton("↔️Back to list↔️", callback_data=f"dl_{str_qry_final}"))]) 215 | reply_markup = InlineKeyboardMarkup(keys) 216 | query.edit_message_text(text=f"""You are now watching **Episode {ep_num_link_get}** of **{tit_url}** :- 217 | 218 | Please share the bot if you like it ☺️. 219 | 220 | __Note: Select HDP link for faster streaming.__ 221 | 222 | **This the Last Episode of the Series 🥳🥳🥳**""", reply_markup=reply_markup, parse_mode="markdown") 223 | elif ep_num_link_get == 1: 224 | key = [] 225 | for links in res_list: 226 | ep_number = links.get('num') 227 | quality = links.get('qual') 228 | download_links = links.get('lnk') 229 | key.append((InlineKeyboardButton(f"Ep{ep_number} {quality}", url=f"{download_links}"))) 230 | n = 3 231 | keys = [key[i:i + n] for i in range(0, len(key), n)] 232 | keys.append([(InlineKeyboardButton("↔️Back To list↔️", callback_data=f"dl_{str_qry_final}")), 233 | (InlineKeyboardButton("Next Ep ⏩", callback_data=f"eps_{ep_num_link_get + 1}_{str_qry_final}"))]) 234 | reply_markup = InlineKeyboardMarkup(keys) 235 | query.edit_message_text(text=f"""You are now watching **Episode {ep_num_link_get}** of **{tit_url}** :- 236 | 237 | Please share the bot if you like it ☺️. 238 | 239 | __Note: Select HDP link for faster streaming.__""", reply_markup=reply_markup, parse_mode="markdown") 240 | else: 241 | key = [] 242 | for links in res_list: 243 | ep_number = links.get('num') 244 | quality = links.get('qual') 245 | download_links = links.get('lnk') 246 | key.append((InlineKeyboardButton(f"Ep{ep_number} {quality}", url=f"{download_links}"))) 247 | n = 3 248 | keys = [key[i:i + n] for i in range(0, len(key), n)] 249 | keys.append([(InlineKeyboardButton("⏪ Previous Ep", callback_data=f"eps_{ep_num_link_get - 1}_{str_qry_final}")), 250 | (InlineKeyboardButton("↔️Back To list↔️", callback_data=f"dl_{str_qry_final}")), 251 | (InlineKeyboardButton("Next Ep ⏩", callback_data=f"eps_{ep_num_link_get + 1}_{str_qry_final}"))]) 252 | reply_markup = InlineKeyboardMarkup(keys) 253 | query.edit_message_text(text=f"""You are now watching **Episode {ep_num_link_get}** of **{tit_url}** :- 254 | 255 | Please share the bot if you like it ☺️. 256 | 257 | __Note: Select HDP link for faster streaming.__""", reply_markup=reply_markup, parse_mode="markdown") -------------------------------------------------------------------------------- /src/get_episodes_index.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2021 BaraniARR 2 | # Encoding = 'utf-8' 3 | # Licensed under MIT License 4 | # Special Thanks for gogoanime 5 | 6 | from pyrogram import * 7 | from pyrogram.types import * 8 | import requests 9 | from requests_html import HTMLSession 10 | from bs4 import BeautifulSoup 11 | 12 | # Splits Inline buttons into ranges of episodes when Episodes counts is greater than 120 13 | 14 | def get_epIndex(client, callback_query): 15 | global list_more_anime 16 | query = callback_query 17 | data = query.data 18 | query.answer("Fetching Episodes...") 19 | data_spl = data.split("_") 20 | # print(data_spl) 21 | animelink = f'https://gogoanime.ai/category/{data_spl[1]}' 22 | response = requests.get(animelink) 23 | plainText = response.text 24 | soup = BeautifulSoup(plainText, "lxml") 25 | tit_url = soup.find("div", {"class": "anime_info_body_bg"}).h1.string 26 | lnk = soup.find(id="episode_page") 27 | try: 28 | source_url = lnk.findAll("li") 29 | for link in source_url: 30 | list_more_anime = [] 31 | list_more_anime.append(link.a) 32 | ep_num_tot = list_more_anime[0].get("ep_end") 33 | ep_num_tot_range = int(ep_num_tot) + 1 34 | if int(ep_num_tot) > 120: 35 | listInitial = [] 36 | for i in range(1, ep_num_tot_range): 37 | listInitial.append(i) 38 | n = 40 39 | listOrganisedInitial = [listInitial[i:i + n] for i in range(0, len(listInitial), n)] 40 | listIndex = [] 41 | for item in listOrganisedInitial: 42 | listIndex.append( 43 | (InlineKeyboardButton(f"{item[0]}-{item.pop()}", 44 | callback_data=f"eplink_{data_spl[1]}_{listOrganisedInitial.index(item)}"))) 45 | o = 3 46 | listIndexFinal = [listIndex[i:i + o] for i in range(0, len(listIndex), o)] 47 | listIndexFinal.append([InlineKeyboardButton("◀️ Back", callback_data=f"dt_{data_spl[1]}")]) 48 | repl = InlineKeyboardMarkup(listIndexFinal) 49 | # print(listIndex) 50 | query.edit_message_text(text=f"""You selected **{tit_url}**, 51 | 52 | Select the Episode you want :-""", reply_markup=repl, parse_mode="markdown") 53 | elif int(ep_num_tot) < 120: 54 | source_url = lnk.find("li").a 55 | ep_num_tot = source_url.get("ep_end") 56 | ep_num_tot_range = int(ep_num_tot) + 1 57 | n = 5 58 | keyb_eps = [] 59 | for i in range(1, ep_num_tot_range): 60 | keyb_eps.append((InlineKeyboardButton(f'{i}', callback_data=f"eps_{i}_{data_spl[1]}"))) 61 | keybrd_inline_butt = [keyb_eps[i:i + n] for i in range(0, len(keyb_eps), n)] 62 | reply_markups = InlineKeyboardMarkup(keybrd_inline_butt) 63 | query.edit_message_text(text=f"""You selected **{tit_url}**, 64 | 65 | Select the Episode you want :-""", reply_markup=reply_markups, parse_mode="markdown") 66 | except: 67 | source_url = lnk.find("li").a 68 | ep_num_tot = source_url.get("ep_end") 69 | ep_num_tot_range = int(ep_num_tot) + 1 70 | n = 5 71 | keyb_eps = [] 72 | for i in range(1, ep_num_tot_range): 73 | keyb_eps.append((InlineKeyboardButton(f'{i}', callback_data=f"eps_{i}_{data_spl[1]}"))) 74 | keybrd_inline_butt = [keyb_eps[i:i + n] for i in range(0, len(keyb_eps), n)] 75 | reply_markups = InlineKeyboardMarkup(keybrd_inline_butt) 76 | query.edit_message_text(text=f"""You selected **{tit_url}**, 77 | 78 | Select the Episode you want :-""", reply_markup=reply_markups, parse_mode="markdown") -------------------------------------------------------------------------------- /src/inline_search.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2021 BaraniARR 2 | # Encoding = 'utf-8' 3 | # Licensed under MIT License 4 | # Special Thanks for gogoanime 5 | 6 | from pyrogram import * 7 | from pyrogram.types import * 8 | import requests 9 | from bs4 import BeautifulSoup 10 | from requests_html import HTMLSession 11 | from uuid import uuid4 12 | 13 | # Inline Anime Search 14 | 15 | def inline_search(client, inline_query): 16 | url = f"https://gogoanime.ai//search.html?keyword={inline_query.query}" 17 | session = HTMLSession() 18 | response = session.get(url) 19 | response_html = response.text 20 | soup = BeautifulSoup(response_html, 'html.parser') 21 | animes = soup.find("ul", {"class": "items"}).find_all("li") 22 | # print(animes) 23 | aAnimes = [] 24 | for anime in animes: # For every anime found 25 | rel = anime.find("p", {"class": "released"}).string 26 | r = rel.split() 27 | rr = "" 28 | released_year = rr.join(r) 29 | tits = anime.a["title"] 30 | urll = anime.a["href"] 31 | imgg = anime.img["src"] 32 | ur = urll.split('/') 33 | url_of_result = ur[2] 34 | aAnimes.append(InlineQueryResultArticle(title=f"{tits}", description=f"{released_year}", 35 | input_message_content=InputTextMessageContent(f"{url_of_result}"), 36 | thumb_url=f"{imgg}")) 37 | inline_query.answer(aAnimes, cache_time=1) -------------------------------------------------------------------------------- /src/inline_search_results.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2021 BaraniARR 2 | # Encoding = 'utf-8' 3 | # Licensed under MIT License 4 | # Special Thanks for gogoanime 5 | 6 | from pyrogram import * 7 | from pyrogram.types import * 8 | import requests 9 | from requests_html import HTMLSession 10 | from bs4 import BeautifulSoup 11 | 12 | # Shows anime details on returned inline search id 13 | 14 | def anime_inline_details(client,message): 15 | try: 16 | animelink = 'https://gogoanime.ai/category/{}'.format(message.text) 17 | response = requests.get(animelink) 18 | plainText = response.text 19 | soup = BeautifulSoup(plainText, "lxml") 20 | source_url = soup.find("div", {"class": "anime_info_body_bg"}).img 21 | # url of anime image 22 | imgg = source_url.get('src') 23 | # print(imgg) 24 | # title name of the anime 25 | tit_url = soup.find("div", {"class": "anime_info_body_bg"}).h1.string 26 | # print(tit_url) 27 | lis = soup.find_all('p', {"class": "type"}) 28 | plot_sum = lis[1] 29 | # print(plot_sum) 30 | pl = plot_sum.get_text().split(':') 31 | pl.remove(pl[0]) 32 | sum = "" 33 | # print plot summary 34 | plot_summary = sum.join(pl) 35 | # print the type of show 36 | type_of_show = lis[0].a['title'] 37 | ai = lis[2].find_all('a') # .find_all('title') 38 | # get list of genres by using genres variable 39 | genres = [] 40 | for link in ai: 41 | genres.append(link.get('title')) 42 | # get released year 43 | year = lis[3].get_text() 44 | # status completed or airing,,, 45 | status = lis[4].a.get_text() 46 | # other names 47 | oth_names = lis[5].get_text() 48 | lnk = soup.find(id="episode_page") 49 | source_url = lnk.find("li").a 50 | # ending ep no 51 | ep_num = int(source_url.get("ep_end")) 52 | kkeeyyb = [ 53 | [InlineKeyboardButton("Download Ad-Free", callback_data=f"dl {message.text}")], 54 | ] 55 | reply_markup = InlineKeyboardMarkup(kkeeyyb) 56 | message.reply_text(f"""[{tit_url}]({imgg}) 57 | 58 | **{tit_url} ({year})** 59 | 60 | **{oth_names}** 61 | 62 | **Type: **`{type_of_show}` 63 | 64 | **Status: **`{status}` 65 | 66 | **Genres: **`{genres}` 67 | 68 | **Episodes: **`{ep_num}` 69 | 70 | **Summary: **`{plot_summary}`""", reply_markup=reply_markup, parse_mode="markdown") 71 | except: 72 | pass -------------------------------------------------------------------------------- /src/instructions.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2021 BaraniARR 2 | # Encoding = 'utf-8' 3 | # Licensed under MIT License 4 | # Special Thanks for gogoanime 5 | 6 | from pyrogram import * 7 | from pyrogram.types import * 8 | 9 | # Totally Optional 10 | 11 | def instructions(client, callback_query): 12 | query = callback_query 13 | query.answer("Please Read Carefully!!!") 14 | keyb = [ 15 | [InlineKeyboardButton("Search Anime Inline", switch_inline_query_current_chat="")] 16 | ] 17 | reply_markup = InlineKeyboardMarkup(keyb) 18 | query.edit_message_caption(caption="""**This Bot can Get your favourite Anime and It provides FREE Download Link with a fastest server(Google drive). ❤️😍** 19 | 20 | **Points to Be Noted :-** 21 | 22 | __👉Since gogoanime changes their domain often, The bot will go for frequent maintenance. Don't worry, the bot will still be online during maintenance.__ 23 | 24 | __👉For streaming in mobile, open the links with VLC Media Player. You can also use MX Player.__ 25 | 26 | __👉For streaming in PC, use VLC media player network stream.__ 27 | 28 | __👉For downloads, just open the links in a browser.__ 29 | 30 | **That's it, You are all caught up, just start and enjoy your favourite anime😁😆** 31 | 32 | **Type /search to Search for an Anime...**""", parse_mode="markdown", reply_markup=reply_markup) 33 | -------------------------------------------------------------------------------- /src/start_message.py: -------------------------------------------------------------------------------- 1 | # Copyright © 2021 BaraniARR 2 | # Encoding = 'utf-8' 3 | # Licensed under MIT License 4 | # Special Thanks for gogoanime 5 | 6 | from pyrogram import * 7 | from pyrogram.types import * 8 | 9 | # Attractive Welcome message 10 | 11 | def start_message(client, message): 12 | kkeeyyb = [ 13 | [InlineKeyboardButton("Instructions", callback_data="instructions")], 14 | ] 15 | reply_markup = InlineKeyboardMarkup(kkeeyyb) 16 | pic_url = "https://drive.google.com/file/d/1TzmuSj05qF6Sm5Z_CSm3AGUCBx4Oe0F0/view?usp=sharing" 17 | message.reply_photo(pic_url, caption=f"""**Hi {message.chat.first_name}**, 18 | 19 | Welcome to Anime DL Bot, Here you can Download all Anime for FREE 😁 ,For TG Anime Join @Anime_Collectors 20 | !!! 21 | 22 | __Please read all the instructions about the bot before surfing on...__ 23 | 24 | See /whats_new to know about latest updates...""", reply_markup=reply_markup, parse_mode="markdown") 25 | --------------------------------------------------------------------------------