Merge pull request #588 from ArjixGamer/patch-27

Added arabic provider EgyAnime
master
AbdullahM0hamed 2020-12-28 22:34:11 +00:00 committed by GitHub
commit c54c9d8927
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 347 additions and 246 deletions

View File

@ -74,6 +74,7 @@ Yeah. Me too! That's why this tool exists.
- Darkanime - Darkanime
- Dbanimes - Dbanimes
- EraiRaws - EraiRaws
- EgyAnime - usually m3u8 (good for streaming, not so much for downloading)
- FastAni - FastAni
- GurminderBoparai (AnimeChameleon) - GurminderBoparai (AnimeChameleon)
- itsaturday - itsaturday

View File

@ -48,6 +48,13 @@ DEFAULT_CONFIG = {
'animefrenzy': { 'animefrenzy': {
'version': 'subbed' 'version': 'subbed'
}, },
'egyanime': {
'version': 'subbed',
'servers': [
'clipwatching',
'streamtape'
]
},
'animebinge': { 'animebinge': {
'version': 'subbed', 'version': 'subbed',
'servers': [ 'servers': [

View File

@ -0,0 +1,18 @@
from anime_downloader.extractors.base_extractor import BaseExtractor
from anime_downloader.sites import helpers
from anime_downloader.util import deobfuscate_packed_js
import re
import json
class clipwatching(BaseExtractor):
def _get_data(self):
fix_json = [['src:', '"src":'], ['type:', '"type":']]
sources = re.search(r"sources:\s*(\[.*?\])", helpers.get(self.url).text).group(1)
for x, y in fix_json:
sources = sources.replace(x, y)
sources = json.loads(sources)
return {
'stream_url': sources[0]['src'],
'referer': self.url
}

View File

@ -1,176 +1,182 @@
from importlib import import_module from importlib import import_module
ALL_EXTRACTORS = [ ALL_EXTRACTORS = [
{ {
'sitename': 'rapidvideo', 'sitename': 'rapidvideo',
'modulename': 'rapidvideo', 'modulename': 'rapidvideo',
'regex': 'rapidvideo', 'regex': 'rapidvideo',
'class': 'RapidVideo' 'class': 'RapidVideo'
}, },
{ {
'sitename': 'no_extractor', 'sitename': 'clipwatching',
'modulename': 'fake_extractor', 'modulename': 'clipwatching',
'regex': 'no_extractor', 'regex': 'clipwatching',
'class': 'AnimeVideo', 'class': 'clipwatching'
}, },
{ {
'sitename': 'animeonline360', 'sitename': 'no_extractor',
'modulename': 'animeonline360', 'modulename': 'fake_extractor',
'regex': 'animeonline360', 'regex': 'no_extractor',
'class': 'AnimeOnline360', 'class': 'AnimeVideo',
}, },
{ {
'sitename': 'stream.moe', 'sitename': 'animeonline360',
'modulename': 'moe', 'modulename': 'animeonline360',
'regex': 'stream.moe', 'regex': 'animeonline360',
'class': 'StreamMoe', 'class': 'AnimeOnline360',
}, },
{ {
'sitename': 'streamango', 'sitename': 'stream.moe',
'modulename': 'streamango', 'modulename': 'moe',
'regex': 'streamango', 'regex': 'stream.moe',
'class': 'Streamango', 'class': 'StreamMoe',
}, },
{ {
'sitename': 'mp4upload', 'sitename': 'streamango',
'modulename': 'mp4upload', 'modulename': 'streamango',
'regex': 'mp4upload', 'regex': 'streamango',
'class': 'MP4Upload' 'class': 'Streamango',
}, },
{ {
'sitename': 'kwik', 'sitename': 'mp4upload',
'modulename': 'kwik', 'modulename': 'mp4upload',
'regex': 'kwik', 'regex': 'mp4upload',
'class': 'Kwik' 'class': 'MP4Upload'
}, },
{ {
'sitename': 'trollvid', 'sitename': 'kwik',
'modulename': 'trollvid', 'modulename': 'kwik',
'regex': 'trollvid', 'regex': 'kwik',
'class': 'Trollvid' 'class': 'Kwik'
}, },
{ {
'sitename': 'mp4sh', 'sitename': 'trollvid',
'modulename': 'mp4sh', 'modulename': 'trollvid',
'regex': 'mp4sh', 'regex': 'trollvid',
'class': 'MP4Sh' 'class': 'Trollvid'
}, },
{ {
'sitename': 'yourupload', 'sitename': 'mp4sh',
'modulename': 'yourupload', 'modulename': 'mp4sh',
'regex': 'yourupload', 'regex': 'mp4sh',
'class': 'Yourupload' 'class': 'MP4Sh'
}, },
{ {
'sitename': 'vidstream', 'sitename': 'yourupload',
'modulename': 'vidstream', 'modulename': 'yourupload',
'regex': 'vidstream', 'regex': 'yourupload',
'class': 'VidStream' 'class': 'Yourupload'
}, },
{ {
'sitename': 'haloani', 'sitename': 'vidstream',
'modulename': 'haloani', 'modulename': 'vidstream',
'regex': 'haloani', 'regex': 'vidstream',
'class': 'Haloani' 'class': 'VidStream'
}, },
{ {
'sitename': 'gcloud', 'sitename': 'haloani',
'modulename': 'gcloud', 'modulename': 'haloani',
'regex': 'gcloud', 'regex': 'haloani',
'class': 'Gcloud' 'class': 'Haloani'
}, },
{ {
'sitename': 'xstreamcdn', 'sitename': 'gcloud',
'modulename': 'xstreamcdn', 'modulename': 'gcloud',
'regex': 'xstreamcdn', 'regex': 'gcloud',
'class': 'XStreamCDN' 'class': 'Gcloud'
}, },
{ {
'sitename': 'cloud9', 'sitename': 'xstreamcdn',
'modulename': 'cloud9', 'modulename': 'xstreamcdn',
'regex': 'cloud9', 'regex': 'xstreamcdn',
'class': 'Cloud9' 'class': 'XStreamCDN'
}, },
{ {
'sitename': 'hydrax', 'sitename': 'cloud9',
'modulename': 'hydrax', 'modulename': 'cloud9',
'regex': 'hydrax', 'regex': 'cloud9',
'class': 'Hydrax' 'class': 'Cloud9'
}, },
{ {
'sitename': 'streamx', 'sitename': 'hydrax',
'modulename': 'streamx', 'modulename': 'hydrax',
'regex': 'streamx', 'regex': 'hydrax',
'class': 'StreamX' 'class': 'Hydrax'
}, },
{ {
'sitename': '3rdparty', 'sitename': 'streamx',
'modulename': '3rdparty', 'modulename': 'streamx',
'regex': '3rdparty', 'regex': 'streamx',
'class': 'Thirdparty' 'class': 'StreamX'
}, },
{ {
'sitename': 'yify', 'sitename': '3rdparty',
'modulename': 'yify', 'modulename': '3rdparty',
'regex': 'yify', 'regex': '3rdparty',
'class': 'Yify' 'class': 'Thirdparty'
}, },
{ {
'sitename': 'mixdrop', 'sitename': 'yify',
'modulename': 'mixdrop', 'modulename': 'yify',
'regex': 'mixdrop', 'regex': 'yify',
'class': 'Mixdrop' 'class': 'Yify'
}, },
{ {
'sitename': 'sendvid', 'sitename': 'mixdrop',
'modulename': 'sendvid', 'modulename': 'mixdrop',
'regex': 'sendvid', 'regex': 'mixdrop',
'class': 'SendVid' 'class': 'Mixdrop'
}, },
{ {
'sitename': 'sibnet', 'sitename': 'sendvid',
'modulename': 'sibnet', 'modulename': 'sendvid',
'regex': 'sibnet', 'regex': 'sendvid',
'class': 'SibNet' 'class': 'SendVid'
}, },
{ {
'sitename': 'uqload', 'sitename': 'sibnet',
'modulename': 'uqload', 'modulename': 'sibnet',
'regex': 'uqload', 'regex': 'sibnet',
'class': 'Uqload' 'class': 'SibNet'
}, },
{ {
'sitename': 'vudeo', 'sitename': 'uqload',
'modulename': 'vudeo', 'modulename': 'uqload',
'regex': 'vudeo', 'regex': 'uqload',
'class': 'Vudeo' 'class': 'Uqload'
}, },
{ {
'sitename': 'eplay', 'sitename': 'vudeo',
'modulename': 'eplay', 'modulename': 'vudeo',
'regex': 'eplay', 'regex': 'vudeo',
'class': 'EPlay' 'class': 'Vudeo'
}, },
{ {
'sitename': 'streamtape', 'sitename': 'eplay',
'modulename': 'streamtape', 'modulename': 'eplay',
'regex': 'streamtape', 'regex': 'eplay',
'class': 'StreamTape' 'class': 'EPlay'
}, },
{ {
'sitename': 'streamium', 'sitename': 'streamtape',
'modulename': 'streamium', 'modulename': 'streamtape',
'regex': 'streamium', 'regex': 'streamtape',
'class': 'Streamium' 'class': 'StreamTape'
} },
] {
'sitename': 'streamium',
'modulename': 'streamium',
def get_extractor(name): 'regex': 'streamium',
for extractor in ALL_EXTRACTORS: 'class': 'Streamium'
if extractor['regex'] in name.lower(): }
module = import_module( ]
'anime_downloader.extractors.{}'.format(
extractor['modulename'])
) def get_extractor(name):
return getattr(module, extractor['class']) for extractor in ALL_EXTRACTORS:
if extractor['regex'] in name.lower():
module = import_module(
'anime_downloader.extractors.{}'.format(
extractor['modulename'])
)
return getattr(module, extractor['class'])

View File

@ -0,0 +1,68 @@
import logging
import re
import urllib.parse
from anime_downloader.sites.anime import Anime, AnimeEpisode, SearchResult
from anime_downloader.sites import helpers
logger = logging.getLogger(__name__)
class EgyAnime(Anime, sitename='egyanime'):
sitename = 'egyanime'
@classmethod
def search(cls, query):
soup = helpers.soupify(helpers.get('https://www.egyanime.com/a.php', params={'term': query}).text)
search_results = [
SearchResult(
title = i.text,
url= "https://www.egyanime.com/" + i['href']
)
for i in soup.find_all('a', href=True)
]
return search_results
def _scrape_episodes(self):
soup = helpers.soupify(helpers.get(self.url).text)
eps = ["https://www.egyanime.com/" + x['href'] for x in soup.select('a.tag.is-dark.is-medium.m-5')]
if len(eps) == 0:
return [self.url.replace('do', 'w')]
return eps
def _scrape_metadata(self):
soup = helpers.soupify(helpers.get(self.url).text)
self.title = soup.title.text.split('مشاهدة')[0].strip()
class EgyAnimeEpisode(AnimeEpisode, sitename='egyanime'):
def _get_sources(self):
soup = helpers.soupify(helpers.get(self.url).text)
servers = soup.select('div.server-watch#server-watch > a')
if servers:
servers = [x['data-link'] for x in servers]
logger.debug('Hosts: ' + str([urllib.parse.urlparse(x).netloc for x in servers]))
else:
servers = soup.find_all('a', {'data-link': True, 'class': 'panel-block'})
servers = [x['data-link'] for x in servers]
sources = []
for i in servers:
if 'clipwatching' in i:
sources.append({
'extractor': 'clipwatching',
'url': i,
'server': 'clipwatching',
'version': '1'
})
elif 'streamtape' in i:
sources.append({
'extractor': 'streamtape',
'url': i,
'server': 'streamtape',
'version': '1'
})
if sources:
return self.sort_sources(sources)
else:
logger.error('No episode source was found, file might have been deleted.')
return

View File

@ -1,70 +1,71 @@
from importlib import import_module from importlib import import_module
ALL_ANIME_SITES = [ ALL_ANIME_SITES = [
# ('filename', 'sitename', 'classname') # ('filename', 'sitename', 'classname')
('_4anime', '4anime', 'Anime4'), ('_4anime', '4anime', 'Anime4'),
('anitube', 'anitube', 'AniTube'), ('anitube', 'anitube', 'AniTube'),
('anime8', 'anime8', 'Anime8'), ('anime8', 'anime8', 'Anime8'),
('animebinge', 'animebinge', 'AnimeBinge'), ('animebinge', 'animebinge', 'AnimeBinge'),
('animechameleon', 'gurminder', 'AnimeChameleon'), ('animechameleon', 'gurminder', 'AnimeChameleon'),
('animedaisuki', 'animedaisuki', 'Animedaisuki'), ('animedaisuki', 'animedaisuki', 'Animedaisuki'),
('animeflix', 'animeflix', 'AnimeFlix'), ('animeflix', 'animeflix', 'AnimeFlix'),
('animeflv', 'animeflv', 'Animeflv'), ('animeflv', 'animeflv', 'Animeflv'),
('animefreak', 'animefreak', 'AnimeFreak'), ('animefreak', 'animefreak', 'AnimeFreak'),
('animefree','animefree','AnimeFree'), ('animefree','animefree','AnimeFree'),
('animefrenzy','animefrenzy','AnimeFrenzy'), ('animefrenzy','animefrenzy','AnimeFrenzy'),
('animekisa','animekisa','AnimeKisa'), ('animekisa','animekisa','AnimeKisa'),
('animetake','animetake','AnimeTake'), ('animetake','animetake','AnimeTake'),
('animeonline','animeonline360','AnimeOnline'), ('animeonline','animeonline360','AnimeOnline'),
('animeout', 'animeout', 'AnimeOut'), ('animeout', 'animeout', 'AnimeOut'),
('animerush', 'animerush', 'AnimeRush'), ('animerush', 'animerush', 'AnimeRush'),
('animesimple', 'animesimple', 'AnimeSimple'), ('animesimple', 'animesimple', 'AnimeSimple'),
('animesuge', 'animesuge', 'AnimeSuge'), ('animesuge', 'animesuge', 'AnimeSuge'),
('animevibe', 'animevibe', 'AnimeVibe'), ('animevibe', 'animevibe', 'AnimeVibe'),
('animixplay', 'animixplay', 'AniMixPlay'), ('animixplay', 'animixplay', 'AniMixPlay'),
('darkanime', 'darkanime', 'DarkAnime'), ('darkanime', 'darkanime', 'DarkAnime'),
('dbanimes', 'dbanimes', 'DBAnimes'), ('dbanimes', 'dbanimes', 'DBAnimes'),
('erairaws', 'erai-raws', 'EraiRaws'), ('erairaws', 'erai-raws', 'EraiRaws'),
('fastani', 'fastani', 'FastAni'), ('egyanime', 'egyanime', 'EgyAnime'),
('itsaturday', 'itsaturday', 'Itsaturday'), ('fastani', 'fastani', 'FastAni'),
('justdubs', 'justdubs', 'JustDubs'), ('itsaturday', 'itsaturday', 'Itsaturday'),
('kickass', 'kickass', 'KickAss'), ('justdubs', 'justdubs', 'JustDubs'),
('kissanimex', 'kissanimex', 'KissAnimeX'), ('kickass', 'kickass', 'KickAss'),
('kisscartoon', 'kisscartoon', 'KissCartoon'), ('kissanimex', 'kissanimex', 'KissAnimeX'),
('nineanime', '9anime', 'NineAnime'), ('kisscartoon', 'kisscartoon', 'KissCartoon'),
('nyaa', 'nyaa', 'Nyaa'), ('nineanime', '9anime', 'NineAnime'),
('putlockers', 'putlockers', 'PutLockers'), ('nyaa', 'nyaa', 'Nyaa'),
('ryuanime', 'ryuanime', 'RyuAnime'), ('putlockers', 'putlockers', 'PutLockers'),
('subsplease', 'subsplease', 'SubsPlease'), ('ryuanime', 'ryuanime', 'RyuAnime'),
('twistmoe', 'twist.moe', 'TwistMoe'), ('subsplease', 'subsplease', 'SubsPlease'),
('tenshimoe', 'tenshi.moe', 'TenshiMoe'), ('twistmoe', 'twist.moe', 'TwistMoe'),
('vidstream', 'vidstream', 'VidStream'), ('tenshimoe', 'tenshi.moe', 'TenshiMoe'),
('voiranime', 'voiranime', 'VoirAnime'), ('vidstream', 'vidstream', 'VidStream'),
('vostfree', 'vostfree', 'VostFree'), ('voiranime', 'voiranime', 'VoirAnime'),
] ('vostfree', 'vostfree', 'VostFree'),
]
def get_anime_class(url):
""" def get_anime_class(url):
Get anime class corresposing to url or name. """
See :py:data:`anime_downloader.sites.ALL_ANIME_SITES` to get the possible anime sites. Get anime class corresposing to url or name.
See :py:data:`anime_downloader.sites.ALL_ANIME_SITES` to get the possible anime sites.
Parameters
---------- Parameters
url: string ----------
URL of the anime. url: string
URL of the anime.
Returns
------- Returns
:py:class:`anime_downloader.sites.anime.Anime` -------
Concrete implementation of :py:class:`anime_downloader.sites.anime.Anime` :py:class:`anime_downloader.sites.anime.Anime`
""" Concrete implementation of :py:class:`anime_downloader.sites.anime.Anime`
for site in ALL_ANIME_SITES: """
if site[1] in url: for site in ALL_ANIME_SITES:
try: if site[1] in url:
module = import_module( try:
'anime_downloader.sites.{}'.format(site[0]) module = import_module(
) 'anime_downloader.sites.{}'.format(site[0])
except ImportError: )
raise except ImportError:
return getattr(module, site[2]) raise
return getattr(module, site[2])