diff --git a/README.md b/README.md index 2cf1c59..3eb98f6 100644 --- a/README.md +++ b/README.md @@ -85,6 +85,7 @@ Yeah. Me too! That's why this tool exists. - Nyaa.si - PutLockers - RyuAnime +- Shiro.is - SubsPlease - twist.moe - requires Node.js - tenshi.moe diff --git a/anime_downloader/sites/init.py b/anime_downloader/sites/init.py index e311118..affdd78 100644 --- a/anime_downloader/sites/init.py +++ b/anime_downloader/sites/init.py @@ -36,6 +36,7 @@ ALL_ANIME_SITES = [ ('nyaa', 'nyaa', 'Nyaa'), ('putlockers', 'putlockers', 'PutLockers'), ('ryuanime', 'ryuanime', 'RyuAnime'), + ('shiro', 'shiro', 'Shiro'), ('subsplease', 'subsplease', 'SubsPlease'), ('twistmoe', 'twist.moe', 'TwistMoe'), ('tenshimoe', 'tenshi.moe', 'TenshiMoe'), diff --git a/anime_downloader/sites/shiro.py b/anime_downloader/sites/shiro.py new file mode 100644 index 0000000..e3eb534 --- /dev/null +++ b/anime_downloader/sites/shiro.py @@ -0,0 +1,71 @@ +import re +import logging +from anime_downloader.sites.anime import Anime, AnimeEpisode, SearchResult +from anime_downloader.sites import helpers + +logger = logging.getLogger(__name__) + + +def get_token(): + r = helpers.get('https://shiro.is').text + script = 'https://shiro.is' + re.search(r'src\=\"(\/static\/js\/main\..*?)\"', r)[1] # noqa + script = helpers.get(script).text + token = re.search(r'token\:\"(.*?)\"', script)[1] + return token + + +class Shiro(Anime, sitename='shiro'): + sitename = 'shiro' + + @classmethod + def search(cls, query): + cls.token = get_token() + params = { + 'search': query, + 'token': cls.token + } + results = helpers.get('https://ani.api-web.site/advanced', params=params).json()['data'] # noqa + if 'nav' in results: + results = results['nav']['currentPage']['items'] + search_results = [ + SearchResult( + title=i['name'], + url='https://shiro.is/anime/' + i['slug'], + poster='https://ani-cdn.api-web.site/' + i['image'], + meta_info={ + 'version_key_dubbed': '(Sub)' if i['language'] == 'subbed' else '(Dub)' # noqa + } + ) + for i in results + ] + search_results = sorted(search_results, key=lambda x: len(x.title)) + return search_results + else: + return [] + + def _scrape_episodes(self): + slug = self.url.replace('https://shiro.is/anime/', '') + api_link = 'https://ani.api-web.site/anime/slug/' + slug + r = helpers.get(api_link, params={'token': self.token}).json() + if r['status'] == 'Found': + episodes = r['data']['episodes'] + episodes = [ + 'https://ani.googledrive.stream/vidstreaming/vid-ad/' + x['videos'][0]['video_id'] # noqa + for x in episodes + ] + return episodes + else: + return [] + + def _scrape_metadata(self): + slug = self.url.replace('https://shiro.is/anime/', '') + api_link = 'https://ani.api-web.site/anime/slug/' + slug + r = helpers.get(api_link, params={'token': self.token}).json() + self.title = r['data']['name'] + + +class ShiroEpisode(AnimeEpisode, sitename='shiro'): + def _get_sources(self): + r = helpers.get(self.url).text + link = re.search(r'\"file\"\:\"(.*?)\"', r)[1] + return [('no_extractor', link)]