external downloader rewrite

master
Vishnunarayan K I 2019-05-08 22:19:12 +05:30
parent 7ccafcab94
commit 8bdaaed839
12 changed files with 298 additions and 54 deletions

View File

@ -13,3 +13,4 @@ sphinx-rtd-theme = "*"
radon = "*" radon = "*"
"flake8" = "*" "flake8" = "*"
httpretty = "*" httpretty = "*"
pylint = "*"

186
Pipfile.lock generated
View File

@ -1,7 +1,7 @@
{ {
"_meta": { "_meta": {
"hash": { "hash": {
"sha256": "01fabf42a826553591227799f7bee2447edf81a6bec93559917576e2b1018c8d" "sha256": "2fdcfcd032fa6e2b1aef868df499755a8a4e1038c2c08d6fbc6ee9cd777d05b8"
}, },
"pipfile-spec": 6, "pipfile-spec": 6,
"requires": {}, "requires": {},
@ -35,9 +35,10 @@
}, },
"cfscrape": { "cfscrape": {
"hashes": [ "hashes": [
"sha256:cb9159955d0e6e82cf4ad8cc9b19413e68ebfed1ce98a26e51f62e66d45146f1" "sha256:0794aa78e586a3af578ff0869f95779bd1702adcdbc9369e8dc470435caaf020",
"sha256:fa7fc172e6872f461377216ddd5a6d82c9650b9d10cac5aa0239998daf3e093a"
], ],
"version": "==1.9.5" "version": "==1.9.7"
}, },
"chardet": { "chardet": {
"hashes": [ "hashes": [
@ -90,17 +91,17 @@
}, },
"requests-cache": { "requests-cache": {
"hashes": [ "hashes": [
"sha256:e9270030becc739b0a7f7f834234c73a878b2d794122bf76f40055a22419eb67", "sha256:6822f788c5ee248995c4bfbd725de2002ad710182ba26a666e85b64981866060",
"sha256:fe561ca119879bbcfb51f03a35e35b425e18f338248e59fd5cf2166c77f457a2" "sha256:73a7211870f7d67af5fd81cad2f67cfe1cd3eb4ee6a85155e07613968cc72dfc"
], ],
"version": "==0.4.13" "version": "==0.5.0"
}, },
"soupsieve": { "soupsieve": {
"hashes": [ "hashes": [
"sha256:afa56bf14907bb09403e5d15fbed6275caa4174d36b975226e3b67a3bb6e2c4b", "sha256:6898e82ecb03772a0d82bd0d0a10c0d6dcc342f77e0701d0ec4a8271be465ece",
"sha256:eaed742b48b1f3e2d45ba6f79401b2ed5dc33b2123dfe216adb90d4bfa0ade26" "sha256:b20eff5e564529711544066d7dc0f7661df41232ae263619dede5059799cdfca"
], ],
"version": "==1.8" "version": "==1.9.1"
}, },
"tabulate": { "tabulate": {
"hashes": [ "hashes": [
@ -110,10 +111,10 @@
}, },
"urllib3": { "urllib3": {
"hashes": [ "hashes": [
"sha256:61bf29cada3fc2fbefad4fdf059ea4bd1b4a86d2b6d15e1c7c0b582b9752fe39", "sha256:4c291ca23bbb55c76518905869ef34bdd5f0e46af7afe6861e8375643ffee1a0",
"sha256:de9529817c93f27c8ccbfead6985011db27bd0ddfcdb2d86f3f663385c6a9c22" "sha256:9a247273df709c4fedb38c711e44292304f73f39ab01beda9f6b9fc375669ac3"
], ],
"version": "==1.24.1" "version": "==1.24.2"
} }
}, },
"develop": { "develop": {
@ -124,6 +125,13 @@
], ],
"version": "==0.7.12" "version": "==0.7.12"
}, },
"astroid": {
"hashes": [
"sha256:6560e1e1749f68c64a4b5dee4e091fce798d2f0d84ebe638cf0e0585a343acf4",
"sha256:b65db1bbaac9f9f4d190199bb8680af6f6f84fd3769a5ea883df8a91fe68b4c4"
],
"version": "==2.2.5"
},
"babel": { "babel": {
"hashes": [ "hashes": [
"sha256:6778d85147d5d85345c14a26aada5e478ab04e39b078b0745ee6870c2b5cf669", "sha256:6778d85147d5d85345c14a26aada5e478ab04e39b078b0745ee6870c2b5cf669",
@ -210,12 +218,53 @@
], ],
"version": "==1.1.0" "version": "==1.1.0"
}, },
"isort": {
"hashes": [
"sha256:01cb7e1ca5e6c5b3f235f0385057f70558b70d2f00320208825fa62887292f43",
"sha256:268067462aed7eb2a1e237fcb287852f22077de3fb07964e87e00f829eea2d1a"
],
"version": "==4.3.17"
},
"jinja2": { "jinja2": {
"hashes": [ "hashes": [
"sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd", "sha256:065c4f02ebe7f7cf559e49ee5a95fb800a9e4528727aec6f24402a5374c65013",
"sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4" "sha256:14dd6caf1527abb21f08f86c784eac40853ba93edb79552aa1e4b8aef1b61c7b"
], ],
"version": "==2.10" "version": "==2.10.1"
},
"lazy-object-proxy": {
"hashes": [
"sha256:0ce34342b419bd8f018e6666bfef729aec3edf62345a53b537a4dcc115746a33",
"sha256:1b668120716eb7ee21d8a38815e5eb3bb8211117d9a90b0f8e21722c0758cc39",
"sha256:209615b0fe4624d79e50220ce3310ca1a9445fd8e6d3572a896e7f9146bbf019",
"sha256:27bf62cb2b1a2068d443ff7097ee33393f8483b570b475db8ebf7e1cba64f088",
"sha256:27ea6fd1c02dcc78172a82fc37fcc0992a94e4cecf53cb6d73f11749825bd98b",
"sha256:2c1b21b44ac9beb0fc848d3993924147ba45c4ebc24be19825e57aabbe74a99e",
"sha256:2df72ab12046a3496a92476020a1a0abf78b2a7db9ff4dc2036b8dd980203ae6",
"sha256:320ffd3de9699d3892048baee45ebfbbf9388a7d65d832d7e580243ade426d2b",
"sha256:50e3b9a464d5d08cc5227413db0d1c4707b6172e4d4d915c1c70e4de0bbff1f5",
"sha256:5276db7ff62bb7b52f77f1f51ed58850e315154249aceb42e7f4c611f0f847ff",
"sha256:61a6cf00dcb1a7f0c773ed4acc509cb636af2d6337a08f362413c76b2b47a8dd",
"sha256:6ae6c4cb59f199d8827c5a07546b2ab7e85d262acaccaacd49b62f53f7c456f7",
"sha256:7661d401d60d8bf15bb5da39e4dd72f5d764c5aff5a86ef52a042506e3e970ff",
"sha256:7bd527f36a605c914efca5d3d014170b2cb184723e423d26b1fb2fd9108e264d",
"sha256:7cb54db3535c8686ea12e9535eb087d32421184eacc6939ef15ef50f83a5e7e2",
"sha256:7f3a2d740291f7f2c111d86a1c4851b70fb000a6c8883a59660d95ad57b9df35",
"sha256:81304b7d8e9c824d058087dcb89144842c8e0dea6d281c031f59f0acf66963d4",
"sha256:933947e8b4fbe617a51528b09851685138b49d511af0b6c0da2539115d6d4514",
"sha256:94223d7f060301b3a8c09c9b3bc3294b56b2188e7d8179c762a1cda72c979252",
"sha256:ab3ca49afcb47058393b0122428358d2fbe0408cf99f1b58b295cfeb4ed39109",
"sha256:bd6292f565ca46dee4e737ebcc20742e3b5be2b01556dafe169f6c65d088875f",
"sha256:cb924aa3e4a3fb644d0c463cad5bc2572649a6a3f68a7f8e4fbe44aaa6d77e4c",
"sha256:d0fc7a286feac9077ec52a927fc9fe8fe2fabab95426722be4c953c9a8bede92",
"sha256:ddc34786490a6e4ec0a855d401034cbd1242ef186c20d79d2166d6a4bd449577",
"sha256:e34b155e36fa9da7e1b7c738ed7767fc9491a62ec6af70fe9da4a057759edc2d",
"sha256:e5b9e8f6bda48460b7b143c3821b21b452cb3a835e6bbd5dd33aa0c8d3f5137d",
"sha256:e81ebf6c5ee9684be8f2c87563880f93eedd56dd2b6146d8a725b50b7e5adb0f",
"sha256:eb91be369f945f10d3a49f5f9be8b3d0b93a4c2be8f8a5b83b0571b8123e0a7a",
"sha256:f460d1ceb0e4a5dcb2a652db0904224f367c9b3c1470d5a7683c0480e582468b"
],
"version": "==1.3.1"
}, },
"mando": { "mando": {
"hashes": [ "hashes": [
@ -299,19 +348,27 @@
], ],
"version": "==2.3.1" "version": "==2.3.1"
}, },
"pylint": {
"hashes": [
"sha256:5d77031694a5fb97ea95e828c8d10fc770a1df6eb3906067aaed42201a8a6a09",
"sha256:723e3db49555abaf9bf79dc474c6b9e2935ad82230b10c1138a71ea41ac0fff1"
],
"index": "pypi",
"version": "==2.3.1"
},
"pyparsing": { "pyparsing": {
"hashes": [ "hashes": [
"sha256:66c9268862641abcac4a96ba74506e594c884e3f57690a696d21ad8210ed667a", "sha256:1873c03321fc118f4e9746baf201ff990ceb915f433f23b395f5580d1840cb2a",
"sha256:f6c5ef0d7480ad048c054c37632c67fca55299990fff127850181659eea33fc3" "sha256:9b6323ef4ab914af344ba97510e966d64ba91055d6b9afa6b30799340e89cc03"
], ],
"version": "==2.3.1" "version": "==2.4.0"
}, },
"pytz": { "pytz": {
"hashes": [ "hashes": [
"sha256:32b0891edff07e28efe91284ed9c31e123d84bea3fd98e1f72be2508f43ef8d9", "sha256:303879e36b721603cc54604edcac9d20401bdbe31e1e4fdee5b9f98d5d31dfda",
"sha256:d5f05e487007e29e03409f9398d074e158d920d36eb82eaf66fb1136b0c5374c" "sha256:d747dd3d23d77ef44c6a3526e274af6efeb0a6f1afd5a69ba4d5be4098c8e141"
], ],
"version": "==2018.9" "version": "==2019.1"
}, },
"radon": { "radon": {
"hashes": [ "hashes": [
@ -358,11 +415,11 @@
}, },
"sphinx": { "sphinx": {
"hashes": [ "hashes": [
"sha256:9f3e17c64b34afc653d7c5ec95766e03043cc6d80b0de224f59b6b6e19d37c3c", "sha256:423280646fb37944dd3c85c58fb92a20d745793a9f6c511f59da82fa97cd404b",
"sha256:c7658aab75c920288a8cf6f09f244c6cfdae30d82d803ac1634d9f223a80ca08" "sha256:de930f42600a4fef993587633984cc5027dedba2464bcf00ddace26b40f8d9ce"
], ],
"index": "pypi", "index": "pypi",
"version": "==1.8.5" "version": "==2.0.1"
}, },
"sphinx-rtd-theme": { "sphinx-rtd-theme": {
"hashes": [ "hashes": [
@ -372,12 +429,47 @@
"index": "pypi", "index": "pypi",
"version": "==0.4.3" "version": "==0.4.3"
}, },
"sphinxcontrib-websupport": { "sphinxcontrib-applehelp": {
"hashes": [ "hashes": [
"sha256:68ca7ff70785cbe1e7bccc71a48b5b6d965d79ca50629606c7861a21b206d9dd", "sha256:edaa0ab2b2bc74403149cb0209d6775c96de797dfd5b5e2a71981309efab3897",
"sha256:9de47f375baf1ea07cdb3436ff39d7a9c76042c10a769c52353ec46e4e8fc3b9" "sha256:fb8dee85af95e5c30c91f10e7eb3c8967308518e0f7488a2828ef7bc191d0d5d"
], ],
"version": "==1.1.0" "version": "==1.0.1"
},
"sphinxcontrib-devhelp": {
"hashes": [
"sha256:6c64b077937330a9128a4da74586e8c2130262f014689b4b89e2d08ee7294a34",
"sha256:9512ecb00a2b0821a146736b39f7aeb90759834b07e81e8cc23a9c70bacb9981"
],
"version": "==1.0.1"
},
"sphinxcontrib-htmlhelp": {
"hashes": [
"sha256:4670f99f8951bd78cd4ad2ab962f798f5618b17675c35c5ac3b2132a14ea8422",
"sha256:d4fd39a65a625c9df86d7fa8a2d9f3cd8299a3a4b15db63b50aac9e161d8eff7"
],
"version": "==1.0.2"
},
"sphinxcontrib-jsmath": {
"hashes": [
"sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178",
"sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"
],
"version": "==1.0.1"
},
"sphinxcontrib-qthelp": {
"hashes": [
"sha256:513049b93031beb1f57d4daea74068a4feb77aa5630f856fcff2e50de14e9a20",
"sha256:79465ce11ae5694ff165becda529a600c754f4bc459778778c7017374d4d406f"
],
"version": "==1.0.2"
},
"sphinxcontrib-serializinghtml": {
"hashes": [
"sha256:c0efb33f8052c04fd7a26c0a07f1678e8512e0faec19f4aa8f2473a8b81d5227",
"sha256:db6615af393650bf1151a6cd39120c29abaf93cc60db8c48eb2dddbfdc3a9768"
],
"version": "==1.1.3"
}, },
"tqdm": { "tqdm": {
"hashes": [ "hashes": [
@ -394,12 +486,38 @@
"index": "pypi", "index": "pypi",
"version": "==1.13.0" "version": "==1.13.0"
}, },
"typed-ast": {
"hashes": [
"sha256:04894d268ba6eab7e093d43107869ad49e7b5ef40d1a94243ea49b352061b200",
"sha256:16616ece19daddc586e499a3d2f560302c11f122b9c692bc216e821ae32aa0d0",
"sha256:252fdae740964b2d3cdfb3f84dcb4d6247a48a6abe2579e8029ab3be3cdc026c",
"sha256:2af80a373af123d0b9f44941a46df67ef0ff7a60f95872412a145f4500a7fc99",
"sha256:2c88d0a913229a06282b285f42a31e063c3bf9071ff65c5ea4c12acb6977c6a7",
"sha256:2ea99c029ebd4b5a308d915cc7fb95b8e1201d60b065450d5d26deb65d3f2bc1",
"sha256:3d2e3ab175fc097d2a51c7a0d3fda442f35ebcc93bb1d7bd9b95ad893e44c04d",
"sha256:4766dd695548a15ee766927bf883fb90c6ac8321be5a60c141f18628fb7f8da8",
"sha256:56b6978798502ef66625a2e0f80cf923da64e328da8bbe16c1ff928c70c873de",
"sha256:5cddb6f8bce14325b2863f9d5ac5c51e07b71b462361fd815d1d7706d3a9d682",
"sha256:644ee788222d81555af543b70a1098f2025db38eaa99226f3a75a6854924d4db",
"sha256:64cf762049fc4775efe6b27161467e76d0ba145862802a65eefc8879086fc6f8",
"sha256:68c362848d9fb71d3c3e5f43c09974a0ae319144634e7a47db62f0f2a54a7fa7",
"sha256:6c1f3c6f6635e611d58e467bf4371883568f0de9ccc4606f17048142dec14a1f",
"sha256:b213d4a02eec4ddf622f4d2fbc539f062af3788d1f332f028a2e19c42da53f15",
"sha256:bb27d4e7805a7de0e35bd0cb1411bc85f807968b2b0539597a49a23b00a622ae",
"sha256:c9d414512eaa417aadae7758bc118868cd2396b0e6138c1dd4fda96679c079d3",
"sha256:f0937165d1e25477b01081c4763d2d9cdc3b18af69cb259dd4f640c9b900fe5e",
"sha256:fb96a6e2c11059ecf84e6741a319f93f683e440e341d4489c9b161eca251cf2a",
"sha256:fc71d2d6ae56a091a8d94f33ec9d0f2001d1cb1db423d8b4355debfe9ce689b7"
],
"markers": "implementation_name == 'cpython'",
"version": "==1.3.4"
},
"urllib3": { "urllib3": {
"hashes": [ "hashes": [
"sha256:61bf29cada3fc2fbefad4fdf059ea4bd1b4a86d2b6d15e1c7c0b582b9752fe39", "sha256:4c291ca23bbb55c76518905869ef34bdd5f0e46af7afe6861e8375643ffee1a0",
"sha256:de9529817c93f27c8ccbfead6985011db27bd0ddfcdb2d86f3f663385c6a9c22" "sha256:9a247273df709c4fedb38c711e44292304f73f39ab01beda9f6b9fc375669ac3"
], ],
"version": "==1.24.1" "version": "==1.24.2"
}, },
"webencodings": { "webencodings": {
"hashes": [ "hashes": [
@ -407,6 +525,12 @@
"sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923" "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"
], ],
"version": "==0.5.1" "version": "==0.5.1"
},
"wrapt": {
"hashes": [
"sha256:4aea003270831cceb8a90ff27c4031da6ead7ec1886023b80ce0dfe0adf61533"
],
"version": "==1.11.1"
} }
} }
} }

1
anime_downloader/.#util.py Symbolic link
View File

@ -0,0 +1 @@
vn-ki@this.1316:1557033979

View File

@ -1,5 +1,12 @@
from anime_downloader.downloader.http_downloader import HTTPDownloader from anime_downloader.downloader.http_downloader import HTTPDownloader
from anime_downloader.downloader.external_downloader import ExternalDownloader
def get_downloader(downloader): def get_downloader(downloader):
"""get_downloader returns the proper downloader class
TODO: Lazy loading of downloaders
"""
if downloader == 'http':
return HTTPDownloader return HTTPDownloader
return ExternalDownloader

View File

@ -10,13 +10,16 @@ logger = logging.getLogger(__name__)
class BaseDownloader: class BaseDownloader:
def __init__(self, source, path, force, range_size=None): def __init__(self, source, path, force, options=None):
logger.info(path) logger.info(path)
self.url = source.stream_url self.url = source.stream_url
self.referer = source.referer self.referer = source.referer
self.path = path self.path = path
self.range_size = range_size
if options is None:
options = {}
self.options = options
util.make_dir(path.rsplit('/', 1)[0]) util.make_dir(path.rsplit('/', 1)[0])

View File

@ -0,0 +1,34 @@
from anime_downloader.downloader.base_downloader import BaseDownloader
from anime_downloader import session
from pathlib import Path
import time
import sys
import subprocess
session = session.get_session()
class ExternalDownloader(BaseDownloader):
def _download(self):
executable = self.options['executable']
opts = self.options['cmd_opts']
path = Path(self.path)
# TODO: Pull this into downloadersession?
rep_dict = {
'stream_url': self.url,
'file_format': str(path.name),
'download_dir': str(path.parent.absolute()),
'referer': self.referer,
}
cmd = [executable] + opts
cmd = [c.format(**rep_dict) for c in cmd]
p = subprocess.Popen(cmd)
return_code = p.wait()
if return_code != 0:
# Sleep for a while to make sure downloader exits correctly
time.sleep(2)
sys.exit(1)

View File

@ -8,13 +8,13 @@ session = session.get_session()
class HTTPDownloader(BaseDownloader): class HTTPDownloader(BaseDownloader):
def _download(self): def _download(self):
if self.range_size is None: if self.options['range_size'] is None:
self._non_range_download() self._non_range_download()
else: else:
self._ranged_download() self._ranged_download()
def _ranged_download(self): def _ranged_download(self):
http_chunksize = self.range_size http_chunksize = self.options['range_size']
range_start = 0 range_start = 0
range_end = http_chunksize range_end = http_chunksize

View File

@ -1,14 +1,18 @@
import logging
import requests import requests
import requests_cache
import urllib3 import urllib3
from requests.adapters import HTTPAdapter from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry from requests.packages.urllib3.util.retry import Retry
import requests_cache import tempfile
import logging from anime_downloader import downloader
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
requests_cache.install_cache('anime_downloader', expires_after=300) file = tempfile.mktemp()
requests_cache.install_cache('anime_downloader', expires_after=300, location=file)
_session = requests_cache.CachedSession() _session = requests_cache.CachedSession()
@ -45,3 +49,32 @@ def get_session(custom_session=None):
_session.hooks = {'response': hook} _session.hooks = {'response': hook}
return _session return _session
class DownloaderSession:
external_downloaders = {
"aria2": {
"executable": "aria2c",
"cmd_opts": [
"{stream_url}", "-x", "12", "-s", "12",
"-j", "12", "-k", "10M", "-o", "{file_format}",
"--continue", "true", "--dir", "{download_dir}",
"--stream-piece-selector", "inorder", "--min-split-size",
"5M", "--referer", "{referer}"
],
"_disable_ssl_additional": ["--check-certificate", "false"],
},
}
def __init__(self, disable_ssl=False):
# TODO: Figure out a way to do disable_ssl elgantly
# Disablining ssl check should be in session and not in
# donwloader because it's a session wise option
# TODO: Add ability to add downloaders using config
pass
def __getitem__(self, key):
if key == 'http':
return downloader.get_downloader('http')()
return self.down

View File

@ -42,7 +42,7 @@ class Anime:
title = '' title = ''
meta = dict() meta = dict()
subclasses = {} subclasses = {}
QUALITIES = None QUALITIES = []
@classmethod @classmethod
def search(cls, query): def search(cls, query):
@ -62,9 +62,13 @@ class Anime:
return return
def __init__(self, url=None, quality='720p', def __init__(self, url=None, quality='720p',
fallback_qualities=['720p', '480p', '360p'], fallback_qualities=None,
_skip_online_data=False): _skip_online_data=False):
self.url = url self.url = url
if fallback_qualities is None:
fallback_qualities = ['720p', '480p', '360p']
self._fallback_qualities = [ self._fallback_qualities = [
q for q in fallback_qualities if q in self.QUALITIES] q for q in fallback_qualities if q in self.QUALITIES]
@ -80,8 +84,8 @@ class Anime:
self._len = len(self._episode_urls) self._len = len(self._episode_urls)
@classmethod @classmethod
def verify_url(self, url): def verify_url(cls, url):
if self.sitename in url: if cls.sitename in url:
return True return True
return False return False
@ -91,6 +95,19 @@ class Anime:
@classmethod @classmethod
def factory(cls, sitename: str): def factory(cls, sitename: str):
"""
factory returns the appropriate subclass for the given site name.
Parameters
----------
sitename: str
sitename is the name of the site
Returns
-------
subclass of :py:class:`Anime`
Sub class of :py:class:`Anime`
"""
return cls.subclasses[sitename] return cls.subclasses[sitename]
@classmethod @classmethod
@ -155,12 +172,13 @@ class Anime:
episode_class = AnimeEpisode.subclasses[self.sitename] episode_class = AnimeEpisode.subclasses[self.sitename]
if isinstance(index, int): if isinstance(index, int):
ep_id = self._episode_urls[index] ep_id = self._episode_urls[index]
return episode_class(ep_id[1], self.quality, parent=self, return episode_class(ep_id[1], parent=self,
ep_no=ep_id[0]) ep_no=ep_id[0])
elif isinstance(index, slice): elif isinstance(index, slice):
anime = copy.deepcopy(self) anime = copy.deepcopy(self)
anime._episode_urls = anime._episode_urls[index] anime._episode_urls = anime._episode_urls[index]
return anime return anime
return None
def __repr__(self): def __repr__(self):
return ''' return '''
@ -175,7 +193,7 @@ Episode count: {length}
def __str__(self): def __str__(self):
return self.title return self.title
def _scarpe_episodes(self, soup): def _scarpe_episodes(self):
""" """
_scarpe_episodes is function which has to be overridden by the base _scarpe_episodes is function which has to be overridden by the base
classes to scrape the episode urls from the web page. classes to scrape the episode urls from the web page.
@ -193,7 +211,7 @@ Episode count: {length}
""" """
return return
def _scrape_metadata(self, soup): def _scrape_metadata(self):
""" """
_scrape_metadata is function which has to be overridden by the base _scrape_metadata is function which has to be overridden by the base
classes to scrape the metadata of anime from the web page. classes to scrape the metadata of anime from the web page.
@ -208,19 +226,40 @@ Episode count: {length}
class AnimeEpisode: class AnimeEpisode:
QUALITIES = None """
Base class for all Episode classes.
Parameters
----------
url: string
URL of the episode.
quality: One of ['360p', '480p', '720p', '1080p']
Quality of episode
fallback_qualities: list
The order of fallback.
Attributes
----------
sitename: str
name of the site
title: str
Title of the anime
meta: dict
metadata about the anime. [Can be empty]
QUALITIES: list
Possible qualities for the site
"""
QUALITIES = []
title = '' title = ''
stream_url = '' stream_url = ''
subclasses = {} subclasses = {}
def __init__(self, url, quality='720p', parent=None, def __init__(self, url, parent: Anime = None, ep_no=None):
ep_no=None):
if quality not in self.QUALITIES:
raise AnimeDLError('Incorrect quality: "{}"'.format(quality))
self.ep_no = ep_no self.ep_no = ep_no
self.url = url self.url = url
self.quality = quality self.quality = parent.quality
self.QUALITIES = parent.QUALITIES
self._parent = parent self._parent = parent
self._sources = None self._sources = None
self.pretty_title = '{}-{}'.format(self._parent.title, self.ep_no) self.pretty_title = '{}-{}'.format(self._parent.title, self.ep_no)

View File

@ -9,6 +9,7 @@ logger = logging.getLogger(__name__)
class KissanimeEpisode(AnimeEpisode, sitename='kissanime'): class KissanimeEpisode(AnimeEpisode, sitename='kissanime'):
"""KissanimeEpisode"""
QUALITIES = ['360p', '480p', '720p', '1080p'] QUALITIES = ['360p', '480p', '720p', '1080p']
_base_url = 'http://kissanime.ru' _base_url = 'http://kissanime.ru'
VERIFY_HUMAN = True VERIFY_HUMAN = True
@ -25,6 +26,7 @@ class KissanimeEpisode(AnimeEpisode, sitename='kissanime'):
class KissAnime(Anime, sitename='kissanime'): class KissAnime(Anime, sitename='kissanime'):
"""KissAnime"""
sitename = 'kissanime' sitename = 'kissanime'
_referer = 'http://kissanime.ru' _referer = 'http://kissanime.ru'
QUALITIES = ['360p', '480p', '720p', '1080p'] QUALITIES = ['360p', '480p', '720p', '1080p']

View File

@ -1,7 +1,6 @@
from Crypto.Cipher import AES from Crypto.Cipher import AES
import base64 import base64
from hashlib import md5 from hashlib import md5
from bs4 import BeautifulSoup
import warnings import warnings
from anime_downloader import session from anime_downloader import session
@ -27,6 +26,7 @@ class TwistMoeEpisode(AnimeEpisode, sitename='twist.moe'):
class TwistMoe(Anime, sitename='twist.moe'): class TwistMoe(Anime, sitename='twist.moe'):
sitename = 'twist.moe'
QUALITIES = ['360p', '480p', '720p', '1080p'] QUALITIES = ['360p', '480p', '720p', '1080p']
_api_url = "https://twist.moe/api/anime/{}/sources" _api_url = "https://twist.moe/api/anime/{}/sources"

View File

@ -193,7 +193,7 @@ def format_command(cmd, episode, file_format, path):
cmd_dict = { cmd_dict = {
'{aria2}': 'aria2c {stream_url} -x 12 -s 12 -j 12 -k 10M -o ' '{aria2}': 'aria2c {stream_url} -x 12 -s 12 -j 12 -k 10M -o '
'{file_format}.mp4 --continue=true --dir={download_dir}' '{file_format}.mp4 --continue=true --dir={download_dir}'
' --stream-piece-selector=inorder --min-split-size=5M --referer={referer}' ' --stream-piece-selector=inorder --min-split-size=5M --referer={referer} --check-certificate=false'
} }
rep_dict = { rep_dict = {
'stream_url': episode.source().stream_url, 'stream_url': episode.source().stream_url,