├── .gitignore ├── README.md ├── linky ├── __init__.py ├── config.py ├── fmovies.py ├── indexsearch.py ├── linkpush.py ├── linky.py ├── log.py ├── myjdownloader.py ├── orion.py ├── pyload.py └── statuscheck.py ├── requirements.txt └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | venv/ 3 | linky.conf 4 | linky.egg-info/ 5 | linky/*.pyc 6 | env/ 7 | linky/__pycache__/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # linky 2 | 3 | `linky` is a work-in-progress command-line tool which can search the internet for movies and TV shows hosted on 1-click hosting websites like OpenLoad (full list of supported hosters coming soon). 4 | 5 | `linky` integrates tightly with [JDownloader](http://jdownloader.org/) and can send any URL (or multiple URLs as a comma-separated list) to a JDownloader "device" via the [my.jdownloader.org](https://my.jdownloader.org/) API or to a [pyLoad](https://pyload.net/) instance. 6 | 7 | At the moment, `linky` uses the [Orion API](https://orionoid.com/) to find links which requires an app key. To acquire an app key, you must sign up for an Orion account and register for an app key via their registration form. 8 | 9 | ## Installation 10 | To install `linky`: 11 | 12 | ``` 13 | # clone this repository 14 | git clone https://github.com/Igglybuff/linky.git && cd linky 15 | 16 | # install it with pip 17 | pip3 install . 18 | 19 | # test that it installed correctly 20 | linky --help 21 | ``` 22 | 23 | ## Usage 24 | ### Configuration 25 | By default, `linky` looks for `~/.config/linky/linky.conf` for configuration. For example, to configure JDownloader, pyLoad, and Orion: 26 | 27 | ``` 28 | [client jdownloader] 29 | default = true 30 | email = foo@bar.com 31 | password = foobar123 32 | device_id = 12345678 33 | 34 | [client pyload] 35 | hostname = localhost 36 | port = 8000 37 | username = pyload 38 | password = pyload 39 | ssl = false 40 | 41 | [indexer orion] 42 | user_key = ABCDEFGHIJ123456 43 | app_key = KLMNOPQRS789012 44 | ``` 45 | 46 | #### MyJDownloader 47 | Sign up for an account and sign in to it on your JDownloader client(s). You can find your client's device ID by clicking on it on the MyJDownloader website and reading the `deviceId=` URL parameter in your address bar. 48 | 49 | ### Searching for links 50 | Only OpenLoad links are returned at the moment, but there are plans to enable setting different sources in the future. 51 | 52 | #### Basic keyword search 53 | 54 | `linky search --hosters openload --indexer orion --media-type movie "White Boy Rick"` 55 | 56 | #### IMDB ID search with 10 results 57 | 58 | `linky search --hosters openload --indexer orion --query-type imdb --media-type movie --results 10 "5519340"` 59 | 60 | #### TMDB ID search for 720p only 61 | 62 | `linky search -w openload -i orion -t tmdb -m movie -q hd1080 -r 6 "424694"` 63 | 64 | ### Sending links to JDownloader 65 | 66 | `linky push --link "" --downloader jdownloader` 67 | 68 | ### Searching and sending a link to JDownloader 69 | 70 | `linky push --link $(linky search --indexer orion "White Boy Rick") --downloader jdownloader` 71 | 72 | ### Checking the status of your downloads 73 | 74 | `linky status --downloader jdownloader` 75 | 76 | ### Planned features 77 | All subcommands: 78 | - [ ] Implement a more convenient way of searching and pushing in the same command 79 | - [x] Implement taking a comma-separated list of URLs as input 80 | - [x] Implement the `--silence` feature to suppress informational log output 81 | - [x] Implement pyLoad integration 82 | - [ ] Implement human-readable output as a default with `--json` as an optional alternative (and maybe `--pretty-print` too) 83 | 84 | `linky search`: 85 | - [x] Implement a `--results` option to print the first n URLs returned from Orion API as a comma-separated list 86 | - [x] Implement a `--hosters` option to set the 1-click-host source 87 | - [x] Implement a `--query-type` option to override the default keyword search, e.g. to search by IMDB/TVDB/TMDB ID. 88 | - [x] Implement a `--quality` option to set the preferred video quality to return 89 | - [ ] Implement an `--age` option to set the maximum number of days since the link was added to the indexer 90 | 91 | `linky push`: 92 | - [ ] Implement a way to print info about pushed links including package ID and file name 93 | 94 | `linky status`: 95 | - [ ] Implement `--all` option to output a report for everything in your download manager (this is the default now) 96 | - [ ] Implement a main argument to get the status of a specific package/download by file name 97 | - [ ] Implement an `--id` option to get the status of a package by ID 98 | - [ ] Implement human-readable output to print % completed, total size, download speed, and name -------------------------------------------------------------------------------- /linky/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Igglybuff/linky/b66ada8b2d57413add48908bcaafc5f85788a5c6/linky/__init__.py -------------------------------------------------------------------------------- /linky/config.py: -------------------------------------------------------------------------------- 1 | import configparser 2 | from os.path import abspath 3 | from .log import info, error, warning 4 | 5 | 6 | class ConfigParser: 7 | 8 | def __init__(self, config, silence): 9 | self.c = abspath(config) 10 | self.silence = silence 11 | self.dict = {} 12 | self.supported_items = { 13 | 'client': ['jdownloader', 'pyload'], 14 | 'indexer': ['fmovies', 'orion'], 15 | } 16 | 17 | def get_config_dict(self): 18 | config = configparser.ConfigParser() 19 | config.read(self.c) 20 | 21 | for section in config.sections(): 22 | self.dict[section] = {} 23 | for key, val in config.items(section): 24 | self.dict[section][key] = val 25 | return self.dict 26 | 27 | def get_sections(self, section_type='all'): 28 | sections_list = [] 29 | config = configparser.ConfigParser() 30 | config.read(self.c) 31 | 32 | if section_type == 'all': 33 | prefix = '' 34 | else: 35 | prefix = section_type 36 | 37 | for section in config.sections(): 38 | if section.startswith(prefix): 39 | sections_list.append(section[len(prefix + ' '):]) 40 | 41 | return sections_list 42 | 43 | def get_client(self, downloader): 44 | if downloader: 45 | downloader = str(downloader).lower() 46 | if str(downloader).lower() in self.supported_items['client']: 47 | return downloader 48 | else: 49 | error(False, 'Provided download client is not supported.') 50 | else: 51 | download_client = self.find_default_config('client') 52 | return download_client 53 | 54 | def find_default_config(self, section_type): 55 | sections = self.get_sections(section_type) 56 | config = self.get_config_dict() 57 | non_defaults = 0 58 | 59 | if len(sections) == 1: 60 | warning(self.silence, 'Skipping searching for defaults and using {} as your {} since it is the only one configured.'.format(str(sections[0]).capitalize(), section_type)) 61 | default = str(sections[0]).lower() 62 | return default 63 | elif len(sections) == 0: 64 | error(False, 'There were no {}s specified in {}'.format(section_type, self.c)) 65 | 66 | for section in sections: 67 | if section in self.supported_items[section_type]: 68 | info(self.silence, 'Found {} in {}'.format(section, self.c)) 69 | if 'default' in config['client {}'.format(section)]: 70 | default_flag = str(config[section]['default']).lower() 71 | if default_flag == 'true': 72 | info(self.silence, '"{}" is set as the default {}!'.format(section, section_type)) 73 | default = section 74 | return default 75 | else: 76 | error(False, 'Found a "default = " line in {} but it is not set to "true".'.format(self.c)) 77 | else: 78 | non_defaults += 1 79 | warning(self.silence, 'Found "{}", a supported {}, but it is not set to default. Looking for additional {}s...'.format(section, section_type, section_type)) 80 | else: 81 | if non_defaults > 1: 82 | error(False, 'At least one {} was found in your configuration, but no default was set!'.format(section_type)) 83 | else: 84 | error(False, 'Something went horribly wrong when reading {} !'.format(self.c)) 85 | 86 | error(False, 'Could not find any supported {}s.'.format(section_type)) 87 | 88 | def get_indexers(self, indexers): 89 | if indexers: 90 | indexers = indexers.lower() 91 | if indexers.lower() in self.supported_items['indexer']: 92 | return indexers 93 | else: 94 | error(False, 'Provided indexer is not supported.') 95 | else: 96 | indexer = self.find_default_config('indexer') 97 | return indexer 98 | 99 | @staticmethod 100 | def split_list(comma_list): 101 | normal_list = [x.strip() for x in comma_list.split(',')] 102 | return normal_list 103 | -------------------------------------------------------------------------------- /linky/fmovies.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from bs4 import BeautifulSoup 3 | from urllib3 import disable_warnings 4 | 5 | 6 | class Fmovies: 7 | 8 | disable_warnings() 9 | 10 | def __init__(self, config): 11 | self.config = config 12 | pass 13 | 14 | def search(self, query): 15 | print('INFO: Searching FMovies for "' + query + '"...') 16 | url = str(self.config['indexer fmovies']['url']) 17 | 18 | headers = { 19 | 'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36', 20 | } 21 | 22 | params = ( 23 | ('keyword', query), 24 | ) 25 | 26 | page = requests.get(url + '/search', headers=headers, params=params) 27 | soup = BeautifulSoup(page.text, 'html.parser') 28 | html_results = soup.find_all('a', {"class": "name"}) 29 | result_url = [result['href'] for result in html_results] 30 | top_result_page_url = url + result_url[0] 31 | 32 | # driver = webdriver.Chrome() 33 | # driver.get(top_result_page_url) 34 | # page = driver.page_source 35 | # print(page) 36 | # soup = BeautifulSoup(page, 'html.parser') 37 | # openload_url = soup.find_all() 38 | 39 | return '' 40 | 41 | def get_cookie(self, url): 42 | 43 | headers = { 44 | 'Accept': 'text/html,application/xhtml+xml,application/xml', 45 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36', 46 | } 47 | 48 | response = requests.get(url, headers=headers, verify=False) 49 | cookie = '; '.join([x.name + '=' + x.value for x in response.cookies]) 50 | 51 | return cookie 52 | -------------------------------------------------------------------------------- /linky/indexsearch.py: -------------------------------------------------------------------------------- 1 | from .fmovies import Fmovies 2 | from .orion import Orion 3 | from .log import warning, info, error 4 | 5 | 6 | class IndexerSearcher: 7 | 8 | def __init__(self, config, silence=False): 9 | self.config = config 10 | self.silence = silence 11 | 12 | def search(self, query, indexers, media_type, hosters, results, query_type, quality): 13 | # TODO: if indexers is a comma-separated list, turn it 14 | # into a list and search all of them 15 | if query_type.lower() == 'imdb': 16 | search_id = 'idimdb' 17 | elif query_type.lower() == 'tvdb': 18 | search_id = 'idtvdb' 19 | elif query_type.lower() == 'tmdb': 20 | search_id = 'idtmdb' 21 | elif query_type.lower() == 'keyword': 22 | search_id = 'query' 23 | else: 24 | error(False, 'Invalid query type "{}" specified.'.format(query_type)) 25 | 26 | if indexers.lower() == 'fmovies': 27 | self.search_fmovies(query) 28 | elif indexers.lower() == 'orion': 29 | self.search_orion(query, media_type, hosters, results, search_id, quality) 30 | else: 31 | error(False, 'Something went wrong searching for "' + query + '"') 32 | 33 | def search_fmovies(self, query): 34 | fm = Fmovies(self.config) 35 | url = fm.search(query) 36 | print(url) 37 | 38 | def search_orion(self, query, media_type, hosters, results, query_type, quality): 39 | orion = Orion(self.config) 40 | url = orion.search(query, media_type, hosters, results, query_type, quality) 41 | print(url) 42 | -------------------------------------------------------------------------------- /linky/linkpush.py: -------------------------------------------------------------------------------- 1 | from .myjdownloader import Jdownloader 2 | from .log import error, info, warning 3 | from .pyload import Pyload 4 | 5 | 6 | class LinkPusher: 7 | 8 | default_client = None 9 | 10 | def __init__(self, config, silence=False): 11 | self.config = config 12 | self.silence = silence 13 | 14 | def push_links(self, links, downloader): 15 | if str(downloader).lower() == 'jdownloader': 16 | self.push_to_jdownloader(links) 17 | elif str(downloader).lower() == 'pyload': 18 | self.push_to_pyload(links) 19 | else: 20 | error(False, 'Something went wrong pushing the link(s) to your download client.') 21 | 22 | def push_to_jdownloader(self, links): 23 | jd = Jdownloader(links, self.config, self.silence) 24 | jd.check_config() 25 | jd.send_to_jdownloader() 26 | 27 | def push_to_pyload(self, links): 28 | pl = Pyload(links, self.config, self.silence) 29 | pl.check_config() 30 | pl.send_to_pyload() 31 | -------------------------------------------------------------------------------- /linky/linky.py: -------------------------------------------------------------------------------- 1 | import click 2 | from os.path import expanduser 3 | from .linkpush import LinkPusher 4 | from .config import ConfigParser 5 | from .indexsearch import IndexerSearcher 6 | from .statuscheck import StatusChecker 7 | 8 | 9 | @click.group() 10 | @click.option('-c', '--config', 'config', 11 | envvar='LINKY_CONFIG_PATH', required=True, 12 | default=expanduser("~") + '/.config/linky/linky.conf', 13 | show_default=True, help='The path to your Linky configuration file.') 14 | @click.option('-s', '--silence', is_flag=True, default=False, 15 | help='Disable log/info output. NOTE: Error messages cannot be silenced.') 16 | @click.pass_context 17 | def linky(ctx, config, silence): 18 | ctx.obj = { 19 | 'CONFIG': config, 20 | 'SILENCE': silence, 21 | } 22 | 23 | 24 | @linky.command() 25 | @click.option('-l', '--link', 'links', required=True, 26 | help='The URL to a file on a premium host that you want to download.') 27 | @click.option('-d', '--downloader', 'downloader', envvar='LINKY_DOWNLOADER', default=None, 28 | help='The name of the download manager you want to use from your configuration file.') 29 | @click.pass_context 30 | def push(ctx, links, downloader): 31 | parser = ConfigParser(ctx.obj['CONFIG'], ctx.obj['SILENCE']) 32 | config = parser.get_config_dict() 33 | download_client = parser.get_client(downloader) 34 | links = parser.split_list(links) 35 | pusher = LinkPusher(config, ctx.obj['SILENCE']) 36 | pusher.push_links(links, download_client) 37 | 38 | 39 | @linky.command() 40 | @click.option('-i', '--indexer', 'indexers', envvar='LINKY_INDEXERS', 41 | required=False, default=None, help='Comma-separated list of indexers to search.') 42 | @click.option('-r', '--results', 'results', required=False, default=1, 43 | help='Number of results to return as a comma-separated list.') 44 | @click.option('-w', '--hosters', 'hosters', required=False, default='openload', 45 | help='Comma-separated list of 1-click-hosters to query.') 46 | @click.option('-t', '--query-type', 'query_type', required=False, default='keyword', 47 | help='Set a different query type instead of doing a keyword search (e.g. "imdb" to search by IMDB ID).') 48 | @click.option('-m', '--media-type', 'media_type', default='movie', required=True, 49 | help='The type of media you want (i.e. "TV" or "Movie").') 50 | @click.option('-q', '--quality', 'quality', required=False, default='hd1080', 51 | help='Desired video quality of links to return (e.g. "hd1080").') 52 | @click.argument('query') 53 | @click.pass_context 54 | def search(ctx, indexers, query, results, hosters, query_type, media_type, quality): 55 | parser = ConfigParser(ctx.obj['CONFIG'], ctx.obj['SILENCE']) 56 | config = parser.get_config_dict() 57 | indexer = parser.get_indexers(indexers) 58 | searcher = IndexerSearcher(config, ctx.obj['SILENCE']) 59 | searcher.search(query, indexer, media_type, hosters, results, query_type, quality) 60 | 61 | 62 | @linky.command() 63 | @click.option('-d', '--downloader', 'downloader', envvar='LINKY_DOWNLOADER', default=None, 64 | help='The name of the download manager you want to use from your configuration file.') 65 | @click.option('-l', '--links', 'links', envvar='LINKY_LINKS', default=None, 66 | help='URLs to files you have sent to your download manager.') 67 | @click.option('-a', '--all', 'all_items', default=False, 68 | help='Get the status for all items in your download manager\' queue.') 69 | @click.pass_context 70 | def status(ctx, downloader, links, all_items): 71 | parser = ConfigParser(ctx.obj['CONFIG'], ctx.obj['SILENCE']) 72 | config = parser.get_config_dict() 73 | download_client = parser.get_client(downloader) 74 | status_checker = StatusChecker(config, download_client, ctx.obj['SILENCE']) 75 | status_checker.get_status(links, all_items) 76 | -------------------------------------------------------------------------------- /linky/log.py: -------------------------------------------------------------------------------- 1 | from sys import exit 2 | 3 | 4 | def error(silence=False, message='Unspecified failure!'): 5 | if silence is False: 6 | print('ERROR: ' + message) 7 | exit(1) 8 | 9 | 10 | def info(silence=False, message='Success!'): 11 | if silence is False: 12 | print('INFO: ' + message) 13 | 14 | 15 | def warning(silence=False, message='Generic warning!'): 16 | if silence is False: 17 | print('WARNING: ' + message) 18 | -------------------------------------------------------------------------------- /linky/myjdownloader.py: -------------------------------------------------------------------------------- 1 | import myjdapi 2 | import json 3 | from .log import error, info, warning 4 | 5 | 6 | class Jdownloader: 7 | 8 | def __init__(self, links, config, silence=False): 9 | self.l = links 10 | self.c = config 11 | self.silence = silence 12 | self.email = self.c['client jdownloader']['email'] 13 | self.password = self.c['client jdownloader']['password'] 14 | self.device_id = self.c['client jdownloader']['device_id'] 15 | 16 | def check_config(self): 17 | self.check_email_format() 18 | self.check_device_id_validity() 19 | self.check_password_exists() 20 | 21 | def check_email_format(self): 22 | # print('Jdownloader email: ' + self.email) 23 | pass 24 | 25 | def check_password_exists(self): 26 | # print('Jdownloader password: ' + self.password) 27 | pass 28 | 29 | def check_device_id_validity(self): 30 | # print('Jdownloader device_id: ' + self.device_id) 31 | pass 32 | 33 | def connect(self): 34 | info(self.silence, 'Connecting to my.jdownloader.org...') 35 | jd = myjdapi.Myjdapi() 36 | jd.connect(self.email, self.password) 37 | info(self.silence, 'Connected!') 38 | return jd 39 | 40 | def send_to_jdownloader(self): 41 | jd = self.connect() 42 | info(self.silence, 'Sending URL(s) to JDownloader...') 43 | for link in self.l: 44 | jd.get_device(device_id=self.device_id).linkgrabber.add_links([{"autostart": True, "links": link}]) 45 | info(self.silence, 'Sent your URL(s) to JDownloader successfully!') 46 | 47 | def check_link_status(self, link=None): 48 | jd = self.connect() 49 | info(self.silence, 'Fetching link(s) status...') 50 | link_status = jd.get_device(device_id=self.device_id).downloads.query_packages() 51 | print(json.dumps(link_status, indent=4, sort_keys=True)) 52 | -------------------------------------------------------------------------------- /linky/orion.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import json 3 | 4 | 5 | class Orion: 6 | 7 | def __init__(self, config): 8 | self.config = config 9 | 10 | def search(self, query, media_type, hosters, results, search_id, quality): 11 | user_key = self.config['indexer orion']['user_key'] 12 | app_key = self.config['indexer orion']['app_key'] 13 | 14 | headers = { 15 | 'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36', 16 | } 17 | 18 | params = ( 19 | ('keyuser', user_key), 20 | ('keyapp', app_key), 21 | ('mode', 'stream'), 22 | ('action', 'retrieve'), 23 | ('type', media_type.lower()), 24 | (search_id, query), 25 | ('limitcount', results), 26 | ('streamtype', 'hoster'), 27 | ('streamhoster', hosters.lower()), 28 | ('videoquality', quality.lower()), 29 | ) 30 | 31 | page = requests.get('https://api.orionoid.com', headers=headers, params=params) 32 | 33 | links = [] 34 | for link in json.loads(page.text)['data']['streams']: 35 | links.append(link['stream']['link']) 36 | 37 | urls = ",".join(links) 38 | 39 | return urls 40 | -------------------------------------------------------------------------------- /linky/pyload.py: -------------------------------------------------------------------------------- 1 | import json 2 | from .log import error, info, warning 3 | import requests 4 | 5 | 6 | class Pyload: 7 | 8 | def __init__(self, links, config, silence=False): 9 | self.l = links 10 | self.c = config 11 | self.silence = silence 12 | self.hostname = self.c['client pyload']['hostname'] 13 | self.port = self.c['client pyload']['port'] 14 | self.username = self.c['client pyload']['username'] 15 | self.password = self.c['client pyload']['password'] 16 | self.ssl = self.c['client pyload']['ssl'] 17 | 18 | if self.ssl == 'true': 19 | protocol = 'https' 20 | else: 21 | protocol = 'http' 22 | 23 | self.url = protocol + '://' + self.hostname + ':' + self.port 24 | 25 | def check_config(self): 26 | pass 27 | 28 | def connect(self): 29 | info(self.silence, 'Connecting to PyLoad at ' + self.url) 30 | 31 | headers = { 32 | 'Connection': 'keep-alive', 33 | 'Cache-Control': 'max-age=0', 34 | 'Origin': self.url, 35 | 'Upgrade-Insecure-Requests': '1', 36 | 'DNT': '1', 37 | 'Content-Type': 'application/x-www-form-urlencoded', 38 | 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36', 39 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 40 | 'Referer': self.url + '/login', 41 | 'Accept-Encoding': 'gzip, deflate, br', 42 | 'Accept-Language': 'en-GB,en;q=0.9,en-US;q=0.8,pt;q=0.7' 43 | } 44 | 45 | data = { 46 | 'do': 'login', 47 | 'username': self.username, 48 | 'password': self.password 49 | } 50 | 51 | session = requests.session() 52 | session.post(self.url + '/login', headers=headers, data=data) 53 | return session 54 | 55 | def send_to_pyload(self): 56 | session = self.connect() 57 | info(self.silence, 'Sending URL(s) to pyLoad...') 58 | 59 | headers = { 60 | 'Content-Type': 'application/json', 61 | } 62 | 63 | for link in self.l: 64 | package_name = link.rsplit('/') 65 | resp = session.post(self.url + '/api/addPackage?name="' + package_name[-1] + '"&links=["' + link + '"]', headers=headers) 66 | if resp.ok: 67 | info(self.silence, 'Sent your URL(s) to pyLoad successfully!') 68 | else: 69 | print('Response: ' + resp.text) 70 | error(self.silence, 'Something went wrong sending link ' + link + ' to pyLoad.') 71 | 72 | def check_link_status(self, link=None): 73 | session = self.connect() 74 | info(self.silence, 'Checking pyLoad queue...') 75 | 76 | headers = { 77 | 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36', 78 | 'Connection': 'keep-alive', 79 | 'Cache-Control': 'max-age=0', 80 | 'Origin': self.url, 81 | 'Upgrade-Insecure-Requests': '1', 82 | 'Content-Type': 'application/json', 83 | } 84 | 85 | resp = session.get(self.url + '/api/getQueue', headers=headers) 86 | json_resp = json.loads(resp.text) 87 | print(json.dumps(json_resp, indent=4, sort_keys=True)) 88 | -------------------------------------------------------------------------------- /linky/statuscheck.py: -------------------------------------------------------------------------------- 1 | from .myjdownloader import Jdownloader 2 | from .log import info, error, warning 3 | from .pyload import Pyload 4 | 5 | 6 | class StatusChecker: 7 | 8 | def __init__(self, config, download_client, silence=False): 9 | self.config = config 10 | self.download_client = download_client 11 | self.silence = silence 12 | 13 | def get_status(self, links=None, all_items=False): 14 | if str(self.download_client).lower() == 'jdownloader': 15 | self.get_jdownloader_status(links) 16 | elif str(self.download_client).lower() == 'pyload': 17 | self.get_pyload_status(links) 18 | else: 19 | error(self.silence, 'Something went wrong checking the status of your link(s).') 20 | 21 | def get_jdownloader_status(self, links): 22 | jd = Jdownloader(links, self.config, self.silence) 23 | jd.check_link_status(links) 24 | 25 | def get_pyload_status(self, links): 26 | pl = Pyload(links, self.config, self.silence) 27 | pl.check_link_status(links) 28 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | myjdapi 2 | click 3 | configparser 4 | requests 5 | bs4 6 | selenium 7 | urllib3 -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, find_packages 2 | 3 | setup( 4 | name='linky', 5 | version='0.1', 6 | packages=find_packages(), 7 | include_package_data=True, 8 | install_requires=[ 9 | 'Click', 10 | ], 11 | entry_points=''' 12 | [console_scripts] 13 | linky=linky.linky:linky 14 | ''', 15 | ) --------------------------------------------------------------------------------