From 111d9e5cdee2e20b0572a6eaa73f52e8c96c2f2b Mon Sep 17 00:00:00 2001 From: justolehlinux <114715041+justolehlinux@users.noreply.github.com> Date: Mon, 6 Feb 2023 02:28:47 +0100 Subject: [PATCH 01/21] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a1d5285..cf7f89c 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,2 @@ -# HDRezkaDownloader +# HDRezkaTool From a49fc55794bc29f32dcca613ecb594dae26e2926 Mon Sep 17 00:00:00 2001 From: justolehlinux <114715041+justolehlinux@users.noreply.github.com> Date: Mon, 6 Feb 2023 02:29:50 +0100 Subject: [PATCH 02/21] Add files via upload --- HDRezkaAPI/download.py | 126 ++++++++++++++++++++++++++------------- HDRezkaAPI/movie_info.py | 19 +++++- 2 files changed, 103 insertions(+), 42 deletions(-) diff --git a/HDRezkaAPI/download.py b/HDRezkaAPI/download.py index 2669d8a..73f1a51 100644 --- a/HDRezkaAPI/download.py +++ b/HDRezkaAPI/download.py @@ -1,9 +1,12 @@ import sys +import os from os import path from bs4 import BeautifulSoup from .request import Request from .get_stream import GetStream from tqdm import tqdm +from slugify import slugify +from pathlib import Path class Error(Exception): @@ -22,12 +25,42 @@ class EpisodeNumberIsOutOfRange(Error): class Download: - def __init__(self, download_data): + def __init__(self, download_data, dorl): self.data = download_data + self.dorl = dorl + self.all = download_data['allepisodes'] self.url = download_data['url'] response = Request().get(self.url) self.soup = BeautifulSoup(response.content, 'html.parser') self.favs = self.soup.find('input', id='ctrl_favs').get('value') + if self.dorl == "pls": + self.name = slugify( + self.data['name'], allow_unicode=True, lowercase=False) + self.filee = open(f"{self.name}.list", "w") + if self.data['translations_list']: + self.translator_id = self.__get_translation() + else: + self.translator_id = self.__detect_translation() + + + def download_all_serial(self): + correct_season = False + seasons_count = self.data['seasons_count'] + while not correct_season: + try: + for season in range(1, seasons_count + 1): + episodes_count = self.data['seasons_episodes_count'][season] + self.download_episodes(season, 1, episodes_count) + correct_season = True + except EpisodeNumberIsOutOfRange: + print('Неверный диапазон эпизодов!') + print('Скачивание успешно завершено!') + + def download_seasons(self, start, end): + for season in range(start, end + 1): + if season < 1 or season > self.data['seasons_count']: + continue + self.download_season(season) def download_season(self, season): if season < 1 or season > self.data['seasons_count']: @@ -38,13 +71,9 @@ def download_season(self, season): 'ul', id=f'simple-episodes-list-{season}') episodes_count = len(episodes_list.findAll('li')) - if self.data['translations_list']: - translator_id = self.__get_translation() - else: - translator_id = self.__detect_translation() - + for i in range(1, episodes_count + 1): - self.download_episode(season, i, translator_id, True) + self.download_episode(season, i, True) def download_episodes(self, season, start, end): if season < 1 or season > self.data['seasons_count']: @@ -58,32 +87,21 @@ def download_episodes(self, season, start, end): if end > episodes_count or start < 0: raise EpisodeNumberIsOutOfRange - if self.data['translations_list']: - translator_id = self.__get_translation() - else: - translator_id = self.__detect_translation() - for i in range(start, end + 1): - self.download_episode(season, i, translator_id, True) + self.download_episode(season, i, True) - def download_episode(self, season, episode, translator_id=None, multi_download=False): + def download_episode(self, season, episode, multi_download=False): if self.data['type'] == 'movie': return if season > self.data['seasons_count']: return - if not multi_download: - if self.data['translations_list']: - translator_id = self.__get_translation() - else: - translator_id = self.__detect_translation() - if episode < 1 or episode > self.data['seasons_episodes_count'][season]: raise IncorrectEpisodeNumberException data = { 'id': self.data['data-id'], - 'translator_id': translator_id, + 'translator_id': self.translator_id, 'favs': self.favs, 'season': season, 'episode': episode, @@ -91,11 +109,18 @@ def download_episode(self, season, episode, translator_id=None, multi_download=F } stream_url = GetStream().get_series_stream(data) - file_name = f"{self.data['name']} {season}s{episode}e.mp4" + downloaded_folder = slugify( + self.data['name'], allow_unicode=True, lowercase=False) + if self.dorl != "pls": + os.makedirs(downloaded_folder, exist_ok=True) + season = str(season).zfill(2) + episode = str(episode).zfill(2) + file_name = f"{downloaded_folder}/s{season}e{episode}.mp4" download_data = { 'stream_url': stream_url, 'file_name': file_name, + } self.__download(download_data) @@ -109,9 +134,9 @@ def download_movie(self): } stream_url = GetStream().get_movie_stream(data) - # file_name = f"{self.data['name']}.mp4" + file_name = f"{self.data['name']}.mp4" # TODO Fix file name bug - file_name = f"test.mp4" + # file_name = f"test.mp4" download_data = { 'stream_url': stream_url, @@ -120,24 +145,45 @@ def download_movie(self): self.__download(download_data) - @staticmethod - def __download(download_data): + def __download(self, download_data): if download_data['stream_url']: + i = 0 + if self.dorl == "pls": + self.filee.write(download_data['stream_url'] + "\n") - fullpath = path.join(path.curdir, download_data['file_name']) - - with Request().get(download_data['stream_url'], stream=True) as r, open(fullpath, "wb") as f, tqdm( - unit="B", - unit_scale=True, - unit_divisor=1024, - total=int(r.headers.get('content-length', 0)), - file=sys.stdout, - desc=download_data['file_name'] - ) as progress: - for chunk in r.iter_content(chunk_size=4096): - if chunk: - datasize = f.write(chunk) - progress.update(datasize) + elif self.data['type'] == 'series': + os.system(f"bomi {download_data['stream_url']}") + else: + fullpath = path.join(path.curdir, download_data['file_name']) + + with Request().get(download_data['stream_url'], stream=True) as r, open(fullpath, "wb") as f, tqdm( + unit="B", + unit_scale=True, + unit_divisor=1024, + total=int(r.headers.get('content-length', 0)), + file=sys.stdout, + desc=download_data['file_name'] + ) as progress: + for chunk in r.iter_content(chunk_size=4096): + if chunk: + datasize = f.write(chunk) + progress.update(datasize) + print(i) + + def convert_to_pls(self): + input_file = self.filee.name + self.filee.close() + with open(input_file, 'r') as f: + url_list = [line.strip() for line in f] + with open(f"{self.name}.pls", 'w') as f: + f.write("[playlist]\n") + for i, url in enumerate(url_list): + f.write(f"File{i+1}={url}\n") + f.write(f"Title{i+1}=Track {i+1}\n") + print(f'Pls len: {len(url_list)}') + print(self.all) + f.write(f"NumberOfEntries={len(url_list)}\n") + f.write("Version=2\n") def __get_translation(self) -> int: for i, translation in zip(range(1, len(self.data['translations_list'])), self.data['translations_list']): diff --git a/HDRezkaAPI/movie_info.py b/HDRezkaAPI/movie_info.py index 13ee114..631c225 100644 --- a/HDRezkaAPI/movie_info.py +++ b/HDRezkaAPI/movie_info.py @@ -16,13 +16,19 @@ def __str__(self): info = self.get_data() if info['type'] == 'movie': s += f'Фильм | {info["name"]}\n' + elif info['type'] == 'Аниме': + s += f'Аниме | {info["name"]}\nКоличество сезонов: {info["seasons_count"]}\n' + s += f'Количество сеp: {info["seasons_episodes_count"]}\n' + s += f'Количество сеp all: {info["allepisodes"]}\n' + else: s += f'Сериал | {info["name"]}\nКоличество сезонов: {info["seasons_count"]}\n' + s += f'Количество сеp: {info["seasons_episodes_count"]}\n' + s += f'Количество сеp all: {info["allepisodes"]}\n' + s += f'Год выпуска: {info["year"]}\n' \ f'Страна:{info["country"]}\n' \ f'Длительность: {info["duration"]}\n' \ - f'Рейтинг IMDb - {info["rating"]["imdb"]}\n' \ - f'Рейтинг Кинопоиск - {info["rating"]["kp"]}\n' \ f'Жанр:' for i in info['genre']: s += f' {i}' @@ -37,6 +43,10 @@ def get_data(self): return self.series_info() elif 'films' in self.url: return self.movie_info() + elif 'cartoons' in self.url: + return self.series_info() + elif 'animation' in self.url: + return self.series_info() else: return 'Wrong link!' @@ -45,6 +55,7 @@ def series_info(self): 'type': 'series', 'name': self.data['name'], 'year': self.data['info']['year'], + 'allepisodes': 0, 'country': self.data['info']['country'], 'seasons_count': len(self.soup.select('#simple-seasons-tabs > li')), 'rating': { @@ -62,13 +73,17 @@ def series_info(self): data.update({'rating': rating}) episodes_count = {} + allepisodes = 0 for i in range(1, data['seasons_count'] + 1): counter = len(self.soup.select(f'#simple-episodes-list-{i} > li')) episodes_count.update({i: counter}) + allepisodes += counter + data.update({'seasons_episodes_count': episodes_count}) + data.update({'allepisodes': allepisodes}) return data def movie_info(self): From e214dfceba0f7743c095a7d5842005d118e3ca07 Mon Sep 17 00:00:00 2001 From: justolehlinux <114715041+justolehlinux@users.noreply.github.com> Date: Mon, 6 Feb 2023 02:32:03 +0100 Subject: [PATCH 03/21] Add files via upload --- main.py | 73 ++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 49 insertions(+), 24 deletions(-) diff --git a/main.py b/main.py index 6e3fca8..ef6e042 100644 --- a/main.py +++ b/main.py @@ -1,5 +1,6 @@ from HDRezkaAPI import * + search_text = input('Поиск: ') search_result = Search(search_text) @@ -12,33 +13,57 @@ download_data = movie_info.get_data() -downloader = Download(download_data) +dorl = input('PLS?') + +downloader = Download(download_data, dorl) print(movie_info) -download_type = int(input('1 - Скачать фильм\n2 - Скачать сезон сериала\n3 - Скачать эпизоды сериала\n' - 'Выберите тип скачивания: ')) -if download_type == 1: +if download_data['type'] == 'movie': downloader.download_movie() print('Скачивание успешно завершено!') -elif download_type == 2: - season = int(input('Введите номер сезона: ')) - downloader.download_season(season) - print('Скачивание успешно завершено!') -elif download_type == 3: - correct_episode = False - season = int(input('Введите номер сезона: ')) - episodes_count = download_data['seasons_episodes_count'][season] - print(f'В данном сезоне количество эпизодов: {episodes_count}') - start = int(input('Введите стартовый эпизод: ')) - end = int(input('Введите конечный эпизод: ')) - while not correct_episode: - try: - downloader.download_episodes(season, start, end) - correct_episode = True - except EpisodeNumberIsOutOfRange: - print('Неверный диапазон!') - episode = int(input('Снова введите диапазон эпизодов: ')) - print('Скачивание успешно завершено!') else: - print('Неверный тип скачивания!') + download_type = int(input('2 - Скачать сезон сериала\n3 - Скачать эпизоды сериала\n4 - Скачать сезонs сериала\n5 - Скачать сериал\n' + 'Выберите тип скачивания: ')) + + if download_type == 2: + season = int(input('Введите номер сезона: ')) + downloader.download_season(season) + print('Скачивание успешно завершено!') + elif download_type == 3: + correct_episode = False + season = int(input('Введите номер сезона: ')) + episodes_count = download_data['seasons_episodes_count'][season] + print(f'В данном сезоне количество эпизодов: {episodes_count}') + start = int(input('Введите стартовый эпизод: ')) + end = int(input('Введите конечный эпизод: ')) + while not correct_episode: + try: + downloader.download_episodes(season, start, end) + correct_episode = True + except EpisodeNumberIsOutOfRange: + print('Неверный диапазон!') + episode = int(input('Снова введите диапазон эпизодов: ')) + print('Скачивание успешно завершено!') + elif download_type == 4: + correct_season = False + start = int(input('Enter the starting season number: ')) + end = int(input('Enter the ending season number: ')) + while not correct_season: + try: + downloader.download_seasons(start, end) + correct_season = True + except SeasonNumberIsOutOfRange: + print('Invalid season range!') + start = int(input('Enter the starting season number again: ')) + end = int(input('Enter the ending season number again: ')) + print('Download successful!') + if download_type == 5: + downloader.download_all_serial() + print('Скачивание успешно завершено!') + if dorl == "pls": + downloader.convert_to_pls() + + + else: + print('Неверный тип скачивания!') From 86067eb6125b528150977dd34511f2319df1ba1b Mon Sep 17 00:00:00 2001 From: justolehlinux <114715041+justolehlinux@users.noreply.github.com> Date: Mon, 6 Feb 2023 02:39:20 +0100 Subject: [PATCH 04/21] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index cf7f89c..4e5614e 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,4 @@ # HDRezkaTool +To add HDRezla libery use +cp -r HDRezkaAPI /usr/lib/python3/dist-packages/ From 273a7c1dd40dd32b90f03597b862d962d257a470 Mon Sep 17 00:00:00 2001 From: justolehlinux <114715041+justolehlinux@users.noreply.github.com> Date: Mon, 6 Feb 2023 02:42:16 +0100 Subject: [PATCH 05/21] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 4e5614e..ce677c4 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ # HDRezkaTool To add HDRezla libery use +```bash cp -r HDRezkaAPI /usr/lib/python3/dist-packages/ +``` From 97cc0f9e886b883577859c547a643e4a0b7a6982 Mon Sep 17 00:00:00 2001 From: justolehlinux <114715041+justolehlinux@users.noreply.github.com> Date: Mon, 6 Feb 2023 18:13:29 +0100 Subject: [PATCH 06/21] Add files via upload MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Создал выбор качества. Но оно спрашивает каждую серию --- HDRezkaAPI/get_stream.py | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/HDRezkaAPI/get_stream.py b/HDRezkaAPI/get_stream.py index 40dfa8a..e777556 100644 --- a/HDRezkaAPI/get_stream.py +++ b/HDRezkaAPI/get_stream.py @@ -22,13 +22,17 @@ def get_series_stream(self, data): try: response = Request().post(request_url, data=data, params=params) r = response.json() + print(r) if r['success'] and not r['url']: print('К сожалению, этот материал не доступен в вашем регионе! ' 'Попробуйте скачать используя VPN!') exit(0) arr = self.decode_url(r['url'], separator="//_//").split(",") - # TODO Make quality select - stream_url = arr[-1][arr[-1].find("or") + 3:len(arr[-1])] + print(arr, "\n ,url") + # stream_url = arr[-1][arr[-1].find("or") + 3:len(arr[-1])] + stream_url = self.quality_select(arr) + print(stream_url) + search_text = input('Поиск: ') decoded = True except (UnicodeDecodeError, BinasciiError): print('Decoding error, trying again!') @@ -50,13 +54,28 @@ def get_movie_stream(self, data): try: arr = self.decode_url(encoded_stream_url, separator="\/\/_\/\/").split(",") - # TODO Make quality select - stream_url = arr[-1][arr[-1].find("or") + 3:len(arr[-1])] + # stream_url = arr[-1][arr[-1].find("or") + 3:len(arr[-1])] + stream_url = self.quality_select(arr) decoded = True except (UnicodeDecodeError, BinasciiError): print('Decoding error, trying again!') return stream_url + + @staticmethod + def quality_select(arr): + input_list = arr + result = [] + for item in input_list: + resolution, url = item.split("]") + if url.endswith(".mp4"): + result.append((resolution + "]", url.split(" or ")[1])) + list = result + for i in range(len(list)): + print(i+1, list[i][0]) + stream_url = list[int(input("Введите номер : ")) - 1][1] + return stream_url + @staticmethod def decode_url(data, separator): From 1f2af7fc043b05c7275258917f9094aa6a734101 Mon Sep 17 00:00:00 2001 From: justolehlinux <114715041+justolehlinux@users.noreply.github.com> Date: Mon, 6 Feb 2023 18:15:35 +0100 Subject: [PATCH 07/21] Add files via upload --- HDRezkaAPI/get_stream.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/HDRezkaAPI/get_stream.py b/HDRezkaAPI/get_stream.py index e777556..2ba9aa6 100644 --- a/HDRezkaAPI/get_stream.py +++ b/HDRezkaAPI/get_stream.py @@ -22,7 +22,6 @@ def get_series_stream(self, data): try: response = Request().post(request_url, data=data, params=params) r = response.json() - print(r) if r['success'] and not r['url']: print('К сожалению, этот материал не доступен в вашем регионе! ' 'Попробуйте скачать используя VPN!') @@ -31,7 +30,6 @@ def get_series_stream(self, data): print(arr, "\n ,url") # stream_url = arr[-1][arr[-1].find("or") + 3:len(arr[-1])] stream_url = self.quality_select(arr) - print(stream_url) search_text = input('Поиск: ') decoded = True except (UnicodeDecodeError, BinasciiError): From 2e54eeec83781db1b650cfba2ab8bf5eba59a263 Mon Sep 17 00:00:00 2001 From: justolehlinux <114715041+justolehlinux@users.noreply.github.com> Date: Mon, 6 Feb 2023 19:01:57 +0100 Subject: [PATCH 08/21] Add files via upload --- HDRezkaAPI/download.py | 9 +++++---- HDRezkaAPI/get_stream.py | 10 ++++------ HDRezkaAPI/search.py | 3 +-- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/HDRezkaAPI/download.py b/HDRezkaAPI/download.py index 73f1a51..83e2280 100644 --- a/HDRezkaAPI/download.py +++ b/HDRezkaAPI/download.py @@ -33,10 +33,11 @@ def __init__(self, download_data, dorl): response = Request().get(self.url) self.soup = BeautifulSoup(response.content, 'html.parser') self.favs = self.soup.find('input', id='ctrl_favs').get('value') + print(self.quality) if self.dorl == "pls": self.name = slugify( self.data['name'], allow_unicode=True, lowercase=False) - self.filee = open(f"{self.name}.list", "w") + self.filee = open(f"{self.data['data-id']}-{self.name}.list", "w") if self.data['translations_list']: self.translator_id = self.__get_translation() else: @@ -109,7 +110,7 @@ def download_episode(self, season, episode, multi_download=False): } stream_url = GetStream().get_series_stream(data) - downloaded_folder = slugify( + downloaded_folder = slugify(self.data['data-id'], self.data['name'], allow_unicode=True, lowercase=False) if self.dorl != "pls": os.makedirs(downloaded_folder, exist_ok=True) @@ -171,9 +172,9 @@ def __download(self, download_data): print(i) def convert_to_pls(self): - input_file = self.filee.name + file_name = self.filee.name self.filee.close() - with open(input_file, 'r') as f: + with open(file_name, 'r') as f: url_list = [line.strip() for line in f] with open(f"{self.name}.pls", 'w') as f: f.write("[playlist]\n") diff --git a/HDRezkaAPI/get_stream.py b/HDRezkaAPI/get_stream.py index 2ba9aa6..6a81f63 100644 --- a/HDRezkaAPI/get_stream.py +++ b/HDRezkaAPI/get_stream.py @@ -27,10 +27,8 @@ def get_series_stream(self, data): 'Попробуйте скачать используя VPN!') exit(0) arr = self.decode_url(r['url'], separator="//_//").split(",") - print(arr, "\n ,url") - # stream_url = arr[-1][arr[-1].find("or") + 3:len(arr[-1])] - stream_url = self.quality_select(arr) - search_text = input('Поиск: ') + stream_url = arr[-1][arr[-1].find("or") + 3:len(arr[-1])] + # stream_url = self.quality_select(arr) decoded = True except (UnicodeDecodeError, BinasciiError): print('Decoding error, trying again!') @@ -52,8 +50,8 @@ def get_movie_stream(self, data): try: arr = self.decode_url(encoded_stream_url, separator="\/\/_\/\/").split(",") - # stream_url = arr[-1][arr[-1].find("or") + 3:len(arr[-1])] - stream_url = self.quality_select(arr) + stream_url = arr[-1][arr[-1].find("or") + 3:len(arr[-1])] + # stream_url = self.quality_select(arr) decoded = True except (UnicodeDecodeError, BinasciiError): print('Decoding error, trying again!') diff --git a/HDRezkaAPI/search.py b/HDRezkaAPI/search.py index 455bc68..a1cef0c 100644 --- a/HDRezkaAPI/search.py +++ b/HDRezkaAPI/search.py @@ -21,8 +21,7 @@ def __iter__(self): def __str__(self): s = '' for title in self.titles_list: - s += (f'{title["id"]} - [{title["info"]["type"]}] Название: {title["name"]} | Год: {title["info"]["year"]} | ' - f'Страна: {title["info"]["country"]} | Жанр: {title["info"]["genre"]}\n') + s += (f'{title["id"]} - [{title["info"]["type"]}] Название: {title["name"]} | Год: {title["info"]["year"]}\n') return s[:-1] def __get_info(self): From 6895da3cb0b7883550efd21f6db4a81277368468 Mon Sep 17 00:00:00 2001 From: justolehlinux <114715041+justolehlinux@users.noreply.github.com> Date: Mon, 6 Feb 2023 23:34:05 +0100 Subject: [PATCH 09/21] Add files via upload --- main.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/main.py b/main.py index ef6e042..323634c 100644 --- a/main.py +++ b/main.py @@ -13,9 +13,14 @@ download_data = movie_info.get_data() -dorl = input('PLS?') +if 0: + dorl = input('PLS?') + quality = input("Введите качество: ") +else: + dorl = "pls" + quality = "1080p]" -downloader = Download(download_data, dorl) +downloader = Download(download_data, dorl, quality) print(movie_info) From 861bfa7e5e037dda850d087cebc4a6981406b583 Mon Sep 17 00:00:00 2001 From: justolehlinux <114715041+justolehlinux@users.noreply.github.com> Date: Mon, 6 Feb 2023 23:35:20 +0100 Subject: [PATCH 10/21] Add files via upload --- HDRezkaAPI/download.py | 27 ++++++++++++++++----------- HDRezkaAPI/get_stream.py | 27 +++++++++++++++++---------- 2 files changed, 33 insertions(+), 21 deletions(-) diff --git a/HDRezkaAPI/download.py b/HDRezkaAPI/download.py index 83e2280..fdb0366 100644 --- a/HDRezkaAPI/download.py +++ b/HDRezkaAPI/download.py @@ -25,15 +25,16 @@ class EpisodeNumberIsOutOfRange(Error): class Download: - def __init__(self, download_data, dorl): + def __init__(self, download_data, dorl, quality): self.data = download_data + self.quality = quality self.dorl = dorl - self.all = download_data['allepisodes'] + if download_data['type'] != 'movie': + self.all = download_data['allepisodes'] self.url = download_data['url'] response = Request().get(self.url) self.soup = BeautifulSoup(response.content, 'html.parser') self.favs = self.soup.find('input', id='ctrl_favs').get('value') - print(self.quality) if self.dorl == "pls": self.name = slugify( self.data['name'], allow_unicode=True, lowercase=False) @@ -77,6 +78,7 @@ def download_season(self, season): self.download_episode(season, i, True) def download_episodes(self, season, start, end): + print(season) if season < 1 or season > self.data['seasons_count']: # TODO Make new custom exception for incorrect season number and realize it return @@ -106,9 +108,11 @@ def download_episode(self, season, episode, multi_download=False): 'favs': self.favs, 'season': season, 'episode': episode, - 'action': 'get_stream' + 'action': 'get_stream', + 'quality': self.quality } - + + print(episode) stream_url = GetStream().get_series_stream(data) downloaded_folder = slugify(self.data['data-id'], self.data['name'], allow_unicode=True, lowercase=False) @@ -131,11 +135,14 @@ def download_movie(self): return data = { - 'url': self.url + 'url': self.url, + 'quality': self.quality } stream_url = GetStream().get_movie_stream(data) - file_name = f"{self.data['name']}.mp4" + mp4 = "mp4" + file_name = slugify(self.data['data-id'], + self.data['name'], mp4, allow_unicode=True, lowercase=False) # TODO Fix file name bug # file_name = f"test.mp4" @@ -148,12 +155,11 @@ def download_movie(self): def __download(self, download_data): if download_data['stream_url']: - i = 0 if self.dorl == "pls": self.filee.write(download_data['stream_url'] + "\n") - elif self.data['type'] == 'series': - os.system(f"bomi {download_data['stream_url']}") + if self.data['type'] == 'movie': + os.system(f"bomi {download_data['stream_url']}") else: fullpath = path.join(path.curdir, download_data['file_name']) @@ -169,7 +175,6 @@ def __download(self, download_data): if chunk: datasize = f.write(chunk) progress.update(datasize) - print(i) def convert_to_pls(self): file_name = self.filee.name diff --git a/HDRezkaAPI/get_stream.py b/HDRezkaAPI/get_stream.py index 6a81f63..04e71b6 100644 --- a/HDRezkaAPI/get_stream.py +++ b/HDRezkaAPI/get_stream.py @@ -27,8 +27,8 @@ def get_series_stream(self, data): 'Попробуйте скачать используя VPN!') exit(0) arr = self.decode_url(r['url'], separator="//_//").split(",") - stream_url = arr[-1][arr[-1].find("or") + 3:len(arr[-1])] - # stream_url = self.quality_select(arr) + # stream_url = arr[-1][arr[-1].find("or") + 3:len(arr[-1])] + stream_url = self.quality_select(arr, data['quality']) decoded = True except (UnicodeDecodeError, BinasciiError): print('Decoding error, trying again!') @@ -50,8 +50,8 @@ def get_movie_stream(self, data): try: arr = self.decode_url(encoded_stream_url, separator="\/\/_\/\/").split(",") - stream_url = arr[-1][arr[-1].find("or") + 3:len(arr[-1])] - # stream_url = self.quality_select(arr) + # stream_url = arr[-1][arr[-1].find("or") + 3:len(arr[-1])] + stream_url = self.quality_select(arr, data['quality']) decoded = True except (UnicodeDecodeError, BinasciiError): print('Decoding error, trying again!') @@ -59,18 +59,25 @@ def get_movie_stream(self, data): return stream_url @staticmethod - def quality_select(arr): + def quality_select(arr, quality): input_list = arr result = [] + num = None for item in input_list: resolution, url = item.split("]") if url.endswith(".mp4"): result.append((resolution + "]", url.split(" or ")[1])) - list = result - for i in range(len(list)): - print(i+1, list[i][0]) - stream_url = list[int(input("Введите номер : ")) - 1][1] - return stream_url + if len(quality) > 2: + for item in input_list: + if quality in item: + num = input_list.index(item) + else: + num = -1 + else: + num = -1 + stream_url = result[num][1] + print(result[num][0], "\n") + return stream_url @staticmethod From 8f5b6e687f453898a6134fbb05f50f57c351ed0f Mon Sep 17 00:00:00 2001 From: justolehlinux <114715041+justolehlinux@users.noreply.github.com> Date: Mon, 11 Mar 2024 16:33:49 +0000 Subject: [PATCH 11/21] testDecError --- ...00-\320\240\320\276\320\261\320\276\321\202.list" | 0 HDRezkaAPI/download.py | 4 +++- README.md | 2 ++ main.py | 12 ++++++------ 4 files changed, 11 insertions(+), 7 deletions(-) create mode 100644 "9364-\320\234\320\270\321\201\321\202\320\265\321\200-\320\240\320\276\320\261\320\276\321\202.list" diff --git "a/9364-\320\234\320\270\321\201\321\202\320\265\321\200-\320\240\320\276\320\261\320\276\321\202.list" "b/9364-\320\234\320\270\321\201\321\202\320\265\321\200-\320\240\320\276\320\261\320\276\321\202.list" new file mode 100644 index 0000000..e69de29 diff --git a/HDRezkaAPI/download.py b/HDRezkaAPI/download.py index fdb0366..425e4da 100644 --- a/HDRezkaAPI/download.py +++ b/HDRezkaAPI/download.py @@ -41,6 +41,8 @@ def __init__(self, download_data, dorl, quality): self.filee = open(f"{self.data['data-id']}-{self.name}.list", "w") if self.data['translations_list']: self.translator_id = self.__get_translation() + # if download_data["seasons_episodes_count"] == 0: + # self.translator_id = self.__get_translation() else: self.translator_id = self.__detect_translation() @@ -115,7 +117,7 @@ def download_episode(self, season, episode, multi_download=False): print(episode) stream_url = GetStream().get_series_stream(data) downloaded_folder = slugify(self.data['data-id'], - self.data['name'], allow_unicode=True, lowercase=False) + self.name, allow_unicode=True, lowercase=False) if self.dorl != "pls": os.makedirs(downloaded_folder, exist_ok=True) season = str(season).zfill(2) diff --git a/README.md b/README.md index ce677c4..4889bf4 100644 --- a/README.md +++ b/README.md @@ -3,4 +3,6 @@ To add HDRezla libery use ```bash cp -r HDRezkaAPI /usr/lib/python3/dist-packages/ +tqdm +python-sl ``` diff --git a/main.py b/main.py index 323634c..63499ec 100644 --- a/main.py +++ b/main.py @@ -17,7 +17,7 @@ dorl = input('PLS?') quality = input("Введите качество: ") else: - dorl = "pls" + dorl = "d" quality = "1080p]" downloader = Download(download_data, dorl, quality) @@ -28,14 +28,14 @@ downloader.download_movie() print('Скачивание успешно завершено!') else: - download_type = int(input('2 - Скачать сезон сериала\n3 - Скачать эпизоды сериала\n4 - Скачать сезонs сериала\n5 - Скачать сериал\n' + download_type = int(input('1 - Скачать сезон сериала\n2 - Скачать эпизоды сериала\n3 - Скачать сезонs сериала\n4 - Скачать сериал\n' 'Выберите тип скачивания: ')) - if download_type == 2: + if download_type == 1: season = int(input('Введите номер сезона: ')) downloader.download_season(season) print('Скачивание успешно завершено!') - elif download_type == 3: + elif download_type == 2: correct_episode = False season = int(input('Введите номер сезона: ')) episodes_count = download_data['seasons_episodes_count'][season] @@ -50,7 +50,7 @@ print('Неверный диапазон!') episode = int(input('Снова введите диапазон эпизодов: ')) print('Скачивание успешно завершено!') - elif download_type == 4: + elif download_type == 3: correct_season = False start = int(input('Enter the starting season number: ')) end = int(input('Enter the ending season number: ')) @@ -63,7 +63,7 @@ start = int(input('Enter the starting season number again: ')) end = int(input('Enter the ending season number again: ')) print('Download successful!') - if download_type == 5: + if download_type == 4: downloader.download_all_serial() print('Скачивание успешно завершено!') if dorl == "pls": From dcf9e3373702b31a954bf57cb58b143cf909b02c Mon Sep 17 00:00:00 2001 From: justolehlinux <114715041+justolehlinux@users.noreply.github.com> Date: Mon, 11 Mar 2024 22:34:12 +0100 Subject: [PATCH 12/21] bro --- HDRezkaAPI/download.py | 14 ++++----- README.md | 3 +- lol.py | 70 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 10 deletions(-) create mode 100644 lol.py diff --git a/HDRezkaAPI/download.py b/HDRezkaAPI/download.py index 425e4da..f7d30d2 100644 --- a/HDRezkaAPI/download.py +++ b/HDRezkaAPI/download.py @@ -35,10 +35,10 @@ def __init__(self, download_data, dorl, quality): response = Request().get(self.url) self.soup = BeautifulSoup(response.content, 'html.parser') self.favs = self.soup.find('input', id='ctrl_favs').get('value') - if self.dorl == "pls": - self.name = slugify( + self.name = slugify(self.data['data-id'], self.data['name'], allow_unicode=True, lowercase=False) - self.filee = open(f"{self.data['data-id']}-{self.name}.list", "w") + if self.dorl == "pls": + self.filee = open(f"{self.name}.list", "w") if self.data['translations_list']: self.translator_id = self.__get_translation() # if download_data["seasons_episodes_count"] == 0: @@ -116,8 +116,7 @@ def download_episode(self, season, episode, multi_download=False): print(episode) stream_url = GetStream().get_series_stream(data) - downloaded_folder = slugify(self.data['data-id'], - self.name, allow_unicode=True, lowercase=False) + downloaded_folder = self.name if self.dorl != "pls": os.makedirs(downloaded_folder, exist_ok=True) season = str(season).zfill(2) @@ -143,20 +142,19 @@ def download_movie(self): stream_url = GetStream().get_movie_stream(data) mp4 = "mp4" - file_name = slugify(self.data['data-id'], - self.data['name'], mp4, allow_unicode=True, lowercase=False) # TODO Fix file name bug # file_name = f"test.mp4" download_data = { 'stream_url': stream_url, - 'file_name': file_name, + 'file_name': self.name, } self.__download(download_data) def __download(self, download_data): if download_data['stream_url']: + print (download_data['file_name']) if self.dorl == "pls": self.filee.write(download_data['stream_url'] + "\n") diff --git a/README.md b/README.md index 4889bf4..68bdebe 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,5 @@ To add HDRezla libery use ```bash cp -r HDRezkaAPI /usr/lib/python3/dist-packages/ -tqdm -python-sl +pip install tqdm python-slugify ``` diff --git a/lol.py b/lol.py new file mode 100644 index 0000000..843b3a2 --- /dev/null +++ b/lol.py @@ -0,0 +1,70 @@ +enable +conf ter +vlan 10 + name v10 +vlan 20 + name v20 +vlan 30 + name v30 + + import os +import pathlib +import sys +import asyncio +import aiohttp +from tqdm import tqdm +from requests import Request + +class MultiDownload: + def __init__(self, data, dorl): + self.data = data + self.dorl = dorl + self.filee = open("download_links.txt", "w") + + async def download(self, download_data): + if download_data['stream_url']: + print (download_data['file_name']) + if self.dorl == "pls": + self.filee.write(download_data['stream_url'] + "\n") + + if self.data['type'] == 'movie': + os.system(f"bomi {download_data['stream_url']}") + else: + fullpath = pathlib.Path.cwd() / download_data['file_name'] + + async with aiohttp.ClientSession() as session: + async with session.get(download_data['stream_url']) as r: + total_size = int(r.headers.get('content-length', 0)) + with open(fullpath, "wb") as f, tqdm( + unit="B", + unit_scale=True, + unit_divisor=1024, + total=total_size, + file=sys.stdout, + desc=download_data['file_name'] + ) as progress: + while True: + chunk = await r.content.read(4096) + if not chunk: + break + datasize = f.write(chunk) + progress.update(datasize) + + async def download_all(self): + tasks = [self.download(download_data) for download_data in self.data['download_data']] + await asyncio.gather(*tasks) + + def start(self): + asyncio.run(self.download_all()) + +# Example usage +data = { + 'type': 'movie', + 'download_data': [ + {'file_name': 'file1.mp4', 'stream_url': 'https://example.com/file1.mp4'}, + {'file_name': 'file2.mp4', 'stream_url': 'https://example.com/file2.mp4'}, + ] +} + +multi_download = MultiDownload(data, dorl="pls") +multi_download.start() \ No newline at end of file From 32ee018c736328d8a33981cad108587bf7fb274b Mon Sep 17 00:00:00 2001 From: Oleh Shvets Date: Tue, 12 Mar 2024 03:16:00 +0100 Subject: [PATCH 13/21] test --- ...\240\320\276\320\261\320\276\321\202.list" | 0 HDRezkaAPI/__init__.py | 1 + HDRezkaAPI/download.py | 22 +++-- HDRezkaAPI/history.py | 91 +++++++++++++++++++ README.md | 2 +- history.json | 1 + main.py | 30 ++++-- 7 files changed, 130 insertions(+), 17 deletions(-) delete mode 100644 "9364-\320\234\320\270\321\201\321\202\320\265\321\200-\320\240\320\276\320\261\320\276\321\202.list" create mode 100644 HDRezkaAPI/history.py create mode 100644 history.json diff --git "a/9364-\320\234\320\270\321\201\321\202\320\265\321\200-\320\240\320\276\320\261\320\276\321\202.list" "b/9364-\320\234\320\270\321\201\321\202\320\265\321\200-\320\240\320\276\320\261\320\276\321\202.list" deleted file mode 100644 index e69de29..0000000 diff --git a/HDRezkaAPI/__init__.py b/HDRezkaAPI/__init__.py index 55fffa6..2eaf63d 100644 --- a/HDRezkaAPI/__init__.py +++ b/HDRezkaAPI/__init__.py @@ -1,3 +1,4 @@ from .search import Search from .movie_info import MovieInfo +from .history import History from .download import * diff --git a/HDRezkaAPI/download.py b/HDRezkaAPI/download.py index f7d30d2..edf4729 100644 --- a/HDRezkaAPI/download.py +++ b/HDRezkaAPI/download.py @@ -4,9 +4,10 @@ from bs4 import BeautifulSoup from .request import Request from .get_stream import GetStream +from .history import History from tqdm import tqdm from slugify import slugify -from pathlib import Path +# from pathlib import Path class Error(Exception): @@ -35,8 +36,8 @@ def __init__(self, download_data, dorl, quality): response = Request().get(self.url) self.soup = BeautifulSoup(response.content, 'html.parser') self.favs = self.soup.find('input', id='ctrl_favs').get('value') - self.name = slugify(self.data['data-id'], - self.data['name'], allow_unicode=True, lowercase=False) + id_and_name = f"{self.data['data-id']} {self.data['name']}" + self.name = slugify(id_and_name, allow_unicode=True, lowercase=False) if self.dorl == "pls": self.filee = open(f"{self.name}.list", "w") if self.data['translations_list']: @@ -161,6 +162,7 @@ def __download(self, download_data): if self.data['type'] == 'movie': os.system(f"bomi {download_data['stream_url']}") else: + History().status = "run" fullpath = path.join(path.curdir, download_data['file_name']) with Request().get(download_data['stream_url'], stream=True) as r, open(fullpath, "wb") as f, tqdm( @@ -175,6 +177,7 @@ def __download(self, download_data): if chunk: datasize = f.write(chunk) progress.update(datasize) + History().status = "end" def convert_to_pls(self): file_name = self.filee.name @@ -192,10 +195,15 @@ def convert_to_pls(self): f.write("Version=2\n") def __get_translation(self) -> int: - for i, translation in zip(range(1, len(self.data['translations_list'])), self.data['translations_list']): - print(f'{i} - {translation["name"]}') - translation_id = self.data['translations_list'][int( - input("Введите номер озвучки: ")) - 1]['id'] + if History().status == 'run': + translation_id = History().translator_id + else: + for i, translation in zip(range(1, len(self.data['translations_list'])), self.data['translations_list']): + print(f'{i} - {translation["name"]}') + translation_id = self.data['translations_list'][int( + input("Введите номер озвучки: ")) - 1]['id'] + History().translator_id = translation_id + return translation_id def __detect_translation(self): diff --git a/HDRezkaAPI/history.py b/HDRezkaAPI/history.py new file mode 100644 index 0000000..68421a4 --- /dev/null +++ b/HDRezkaAPI/history.py @@ -0,0 +1,91 @@ +import json + +class History: + def __init__(self): + self._load_data() + + def _load_data(self): + try: + with open('history.json', 'r') as json_file: + data = json.load(json_file) + self._movie_data = data.get('movie_data', {}) + self._quality = data.get('quality', '') + self._dorl = data.get('dorl', '') + self._download_type = data.get('download_type', {}) + self._translator_id = data.get('translator_id', '') + self._status = data.get('status', '') + except FileNotFoundError: + self._movie_data = {} + self._quality = '' + self._dorl = '' + self._download_type = {} + self._translator_id = '' + self._status = '' + + def _save_data(self): + data = { + 'movie_data': self._movie_data, + 'quality': self._quality, + 'dorl': self._dorl, + 'download_type': self._download_type, + 'translator_id': self._translator_id, + 'status': self._status + } + with open('history.json', 'w') as json_file: + json.dump(data, json_file) + + @property + def movie_data(self): + return self._movie_data + + @movie_data.setter + def movie_data(self, value): + self._movie_data = value + self._save_data() + + @property + def quality(self): + return self._quality + + @quality.setter + def quality(self, value): + self._quality = value + self._save_data() + + @property + def dorl(self): + return self._dorl + + @dorl.setter + def dorl(self, value): + self._dorl = value + self._save_data() + + @property + def download_type(self): + return self._download_type + + @download_type.setter + def download_type(self, value): + self._download_type = value + self._save_data() + + @property + def translator_id(self): + return self._translator_id + + @translator_id.setter + def translator_id(self, value): + self._translator_id = value + self._save_data() + + @property + def status(self): + return self._status + + @status.setter + def status(self, value): + self._status = value + self._save_data() + + diff --git a/README.md b/README.md index 68bdebe..e1291bc 100644 --- a/README.md +++ b/README.md @@ -3,5 +3,5 @@ To add HDRezla libery use ```bash cp -r HDRezkaAPI /usr/lib/python3/dist-packages/ -pip install tqdm python-slugify +pip install tqdm python-slugify aiohttp ``` diff --git a/history.json b/history.json new file mode 100644 index 0000000..79df669 --- /dev/null +++ b/history.json @@ -0,0 +1 @@ +{"movie_data": {"id": 23, "name": "\u041c\u0438\u0441\u0442\u0435\u0440 \u0420\u043e\u0431\u043e\u0442", "info": {"type": "\u0421\u0435\u0440\u0438\u0430\u043b", "year": "2015-2019", "country": " \u0421\u0428\u0410", "genre": " \u0422\u0440\u0438\u043b\u043b\u0435\u0440\u044b"}, "data-id": "9364", "url": "https://rezka.ag/series/thriller/9364-mister-robot-2015.html"}, "quality": "", "dorl": "", "download_type": 4, "translator_id": "56", "status": "run"} \ No newline at end of file diff --git a/main.py b/main.py index 63499ec..ef6e2b4 100644 --- a/main.py +++ b/main.py @@ -1,17 +1,23 @@ from HDRezkaAPI import * +if History().status == 'run' and input('Continue[yN]?') != "n": + movie_data = History().movie_data +else: + search_text = input('Поиск: ') + search_result = Search(search_text) + + print(search_result) -search_text = input('Поиск: ') -search_result = Search(search_text) + title_id = int(input('Введите номер: ')) -print(search_result) + movie_data = search_result.get_data(title_id) -title_id = int(input('Введите номер: ')) +History().movie_data = movie_data -movie_data = search_result.get_data(title_id) movie_info = MovieInfo(movie_data) download_data = movie_info.get_data() +print (f'\n{download_data}\n') if 0: dorl = input('PLS?') @@ -27,9 +33,14 @@ if download_data['type'] == 'movie': downloader.download_movie() print('Скачивание успешно завершено!') -else: - download_type = int(input('1 - Скачать сезон сериала\n2 - Скачать эпизоды сериала\n3 - Скачать сезонs сериала\n4 - Скачать сериал\n' +else: + + if History().status == 'run': + download_type = History().download_type + else: + download_type = int(input('1 - Скачать сезон сериала\n2 - Скачать эпизоды сериала\n3 - Скачать сезонs сериала\n4 - Скачать сериал\n' 'Выберите тип скачивания: ')) + History().download_type = download_type if download_type == 1: season = int(input('Введите номер сезона: ')) @@ -41,7 +52,7 @@ episodes_count = download_data['seasons_episodes_count'][season] print(f'В данном сезоне количество эпизодов: {episodes_count}') start = int(input('Введите стартовый эпизод: ')) - end = int(input('Введите конечный эпизод: ')) + end = episodes_count while not correct_episode: try: downloader.download_episodes(season, start, end) @@ -63,12 +74,13 @@ start = int(input('Enter the starting season number again: ')) end = int(input('Enter the ending season number again: ')) print('Download successful!') - if download_type == 4: + elif download_type == 4: downloader.download_all_serial() print('Скачивание успешно завершено!') if dorl == "pls": downloader.convert_to_pls() + else: print('Неверный тип скачивания!') From 9ff7db06dbab7c6406f4857dff4c4cfa7f38e36c Mon Sep 17 00:00:00 2001 From: Oleh Shvets Date: Thu, 21 Mar 2024 01:04:39 +0100 Subject: [PATCH 14/21] Update download.py, get\_stream.py, history.py for new functionality and fix bugs * In download.py, added new attributes and methods for handling season and episode numbers, fixed bugs in downloading episodes and seasons, and improved code readability. * In get\_stream.py, added a new method for selecting stream quality and improved code readability. * In history.py, added new attributes and methods for storing and retrieving season and episode numbers, and improved code readability. * Updated README.md to reflect changes in required packages. * Updated main.py to use new functionality and fixed bugs. --- HDRezkaAPI/download.py | 98 +++++++++++++++++++++------------------- HDRezkaAPI/get_stream.py | 34 +++++++------- HDRezkaAPI/history.py | 26 ++++++++++- README.md | 2 +- history.json | 2 +- main.py | 19 ++++---- 6 files changed, 107 insertions(+), 74 deletions(-) diff --git a/HDRezkaAPI/download.py b/HDRezkaAPI/download.py index edf4729..817e8ef 100644 --- a/HDRezkaAPI/download.py +++ b/HDRezkaAPI/download.py @@ -6,8 +6,6 @@ from .get_stream import GetStream from .history import History from tqdm import tqdm -from slugify import slugify -# from pathlib import Path class Error(Exception): @@ -30,14 +28,12 @@ def __init__(self, download_data, dorl, quality): self.data = download_data self.quality = quality self.dorl = dorl - if download_data['type'] != 'movie': - self.all = download_data['allepisodes'] self.url = download_data['url'] response = Request().get(self.url) self.soup = BeautifulSoup(response.content, 'html.parser') - self.favs = self.soup.find('input', id='ctrl_favs').get('value') - id_and_name = f"{self.data['data-id']} {self.data['name']}" - self.name = slugify(id_and_name, allow_unicode=True, lowercase=False) + # self.favs = self.soup.find('input', id='ctrl_favs').get('value') + self.name = download_data['url'].split('/')[-1].split('.')[0] + if self.dorl == "pls": self.filee = open(f"{self.name}.list", "w") if self.data['translations_list']: @@ -53,10 +49,13 @@ def download_all_serial(self): seasons_count = self.data['seasons_count'] while not correct_season: try: - for season in range(1, seasons_count + 1): - episodes_count = self.data['seasons_episodes_count'][season] - self.download_episodes(season, 1, episodes_count) - correct_season = True + if History().status == 'run' and History().run_season !="": + season = History().run_season() + self.download_seasons(season, seasons_count +1) + else: + for season in range(1, seasons_count + 1): + self.download_season(season) + correct_season = True except EpisodeNumberIsOutOfRange: print('Неверный диапазон эпизодов!') print('Скачивание успешно завершено!') @@ -72,16 +71,20 @@ def download_season(self, season): # TODO Make new custom exception for incorrect season number and realize it return - episodes_list = self.soup.find( - 'ul', id=f'simple-episodes-list-{season}') - episodes_count = len(episodes_list.findAll('li')) + episodes_count = self.data['seasons_episodes_count'][season] + History().run_season = season - - for i in range(1, episodes_count + 1): - self.download_episode(season, i, True) + if History().status == 'run' and History().run_episode !="": + start = History( ).run_episode + else: + start = 1 - def download_episodes(self, season, start, end): + for i in range(start, episodes_count + 1): + self.download_episode(season, i) + + def download_episodes(self, season, start): print(season) + end = self.data['seasons_episodes_count'][season] if season < 1 or season > self.data['seasons_count']: # TODO Make new custom exception for incorrect season number and realize it return @@ -94,9 +97,9 @@ def download_episodes(self, season, start, end): raise EpisodeNumberIsOutOfRange for i in range(start, end + 1): - self.download_episode(season, i, True) + self.download_episode(season, i) - def download_episode(self, season, episode, multi_download=False): + def download_episode(self, season, episode): if self.data['type'] == 'movie': return if season > self.data['seasons_count']: @@ -108,7 +111,7 @@ def download_episode(self, season, episode, multi_download=False): data = { 'id': self.data['data-id'], 'translator_id': self.translator_id, - 'favs': self.favs, + # 'favs': self.favs, 'season': season, 'episode': episode, 'action': 'get_stream', @@ -116,6 +119,8 @@ def download_episode(self, season, episode, multi_download=False): } print(episode) + History().run_episode = episode + stream_url = GetStream().get_series_stream(data) downloaded_folder = self.name if self.dorl != "pls": @@ -142,7 +147,6 @@ def download_movie(self): } stream_url = GetStream().get_movie_stream(data) - mp4 = "mp4" # TODO Fix file name bug # file_name = f"test.mp4" @@ -153,31 +157,33 @@ def download_movie(self): self.__download(download_data) - def __download(self, download_data): + @staticmethod + def __download( download_data): if download_data['stream_url']: print (download_data['file_name']) - if self.dorl == "pls": - self.filee.write(download_data['stream_url'] + "\n") - - if self.data['type'] == 'movie': - os.system(f"bomi {download_data['stream_url']}") - else: - History().status = "run" - fullpath = path.join(path.curdir, download_data['file_name']) - - with Request().get(download_data['stream_url'], stream=True) as r, open(fullpath, "wb") as f, tqdm( - unit="B", - unit_scale=True, - unit_divisor=1024, - total=int(r.headers.get('content-length', 0)), - file=sys.stdout, - desc=download_data['file_name'] - ) as progress: - for chunk in r.iter_content(chunk_size=4096): - if chunk: - datasize = f.write(chunk) - progress.update(datasize) - History().status = "end" + # if self.dorl == "pls": + # self.filee.write(download_data['stream_url'] + "\n") + + # if self.data['type'] == 'movie': + # os.system(f"bomi {download_data['stream_url']}") + # else: + History().status = "run" + fullpath = path.join(path.curdir, download_data['file_name']) + + with Request().get(download_data['stream_url'], stream=True) as r, open(fullpath, "wb") as f, tqdm( + unit="B", + unit_scale=True, + unit_divisor=1024, + total=int(r.headers.get('content-length', 0)), + file=sys.stdout, + desc=download_data['file_name'] + ) as progress: + for chunk in r.iter_content(chunk_size=4096): + if chunk: + datasize = f.write(chunk) + progress.update(datasize) + History().run_episode = History().run_episode + 1 + def convert_to_pls(self): file_name = self.filee.name @@ -190,7 +196,7 @@ def convert_to_pls(self): f.write(f"File{i+1}={url}\n") f.write(f"Title{i+1}=Track {i+1}\n") print(f'Pls len: {len(url_list)}') - print(self.all) + print(self.download_data['allepisodes']) f.write(f"NumberOfEntries={len(url_list)}\n") f.write("Version=2\n") diff --git a/HDRezkaAPI/get_stream.py b/HDRezkaAPI/get_stream.py index 04e71b6..b2d0b23 100644 --- a/HDRezkaAPI/get_stream.py +++ b/HDRezkaAPI/get_stream.py @@ -27,7 +27,6 @@ def get_series_stream(self, data): 'Попробуйте скачать используя VPN!') exit(0) arr = self.decode_url(r['url'], separator="//_//").split(",") - # stream_url = arr[-1][arr[-1].find("or") + 3:len(arr[-1])] stream_url = self.quality_select(arr, data['quality']) decoded = True except (UnicodeDecodeError, BinasciiError): @@ -59,25 +58,26 @@ def get_movie_stream(self, data): return stream_url @staticmethod - def quality_select(arr, quality): - input_list = arr - result = [] - num = None - for item in input_list: + def quality_select(stream_list, quality): + resolutions_and_urls = [] + for item in stream_list: resolution, url = item.split("]") if url.endswith(".mp4"): - result.append((resolution + "]", url.split(" or ")[1])) - if len(quality) > 2: - for item in input_list: + resolutions_and_urls.append((resolution + "]", url.split(" or ")[1])) + + selected_index = -2 + if len(quality) > 2: + for index, item in enumerate(stream_list): if quality in item: - num = input_list.index(item) - else: - num = -1 - else: - num = -1 - stream_url = result[num][1] - print(result[num][0], "\n") - return stream_url + selected_index = index + break + + # if selected_index == -1: + # raise ValueError("Quality not found or invalid") + + stream_url = resolutions_and_urls[selected_index][1] + print(resolutions_and_urls[selected_index][0], "\n") + return stream_url @staticmethod diff --git a/HDRezkaAPI/history.py b/HDRezkaAPI/history.py index 68421a4..96733af 100644 --- a/HDRezkaAPI/history.py +++ b/HDRezkaAPI/history.py @@ -14,6 +14,8 @@ def _load_data(self): self._download_type = data.get('download_type', {}) self._translator_id = data.get('translator_id', '') self._status = data.get('status', '') + self._run_season = data.get('run_season', '') + self._run_episode = data.get('run_episode', '') except FileNotFoundError: self._movie_data = {} self._quality = '' @@ -21,6 +23,8 @@ def _load_data(self): self._download_type = {} self._translator_id = '' self._status = '' + self._run_season = '' + self._run_episode = '' def _save_data(self): data = { @@ -29,7 +33,9 @@ def _save_data(self): 'dorl': self._dorl, 'download_type': self._download_type, 'translator_id': self._translator_id, - 'status': self._status + 'status': self._status, + 'run_season': self._run_season, + 'run_episode': self._run_episode } with open('history.json', 'w') as json_file: json.dump(data, json_file) @@ -88,4 +94,22 @@ def status(self, value): self._status = value self._save_data() + @property + def run_season(self): + return self._run_season + + @run_season.setter + def run_season(self, value): + self._run_season = value + self._save_data() + + @property + def run_episode(self): + return self._run_episode + + @run_episode.setter + def run_episode(self, value): + self._run_episode = value + self._save_data() + diff --git a/README.md b/README.md index e1291bc..e1c7684 100644 --- a/README.md +++ b/README.md @@ -3,5 +3,5 @@ To add HDRezla libery use ```bash cp -r HDRezkaAPI /usr/lib/python3/dist-packages/ -pip install tqdm python-slugify aiohttp +pip install tqdm bs4 ``` diff --git a/history.json b/history.json index 79df669..bd6d92e 100644 --- a/history.json +++ b/history.json @@ -1 +1 @@ -{"movie_data": {"id": 23, "name": "\u041c\u0438\u0441\u0442\u0435\u0440 \u0420\u043e\u0431\u043e\u0442", "info": {"type": "\u0421\u0435\u0440\u0438\u0430\u043b", "year": "2015-2019", "country": " \u0421\u0428\u0410", "genre": " \u0422\u0440\u0438\u043b\u043b\u0435\u0440\u044b"}, "data-id": "9364", "url": "https://rezka.ag/series/thriller/9364-mister-robot-2015.html"}, "quality": "", "dorl": "", "download_type": 4, "translator_id": "56", "status": "run"} \ No newline at end of file +{"movie_data": {"id": 23, "name": "\u041c\u0438\u0441\u0442\u0435\u0440 \u0420\u043e\u0431\u043e\u0442", "info": {"type": "\u0421\u0435\u0440\u0438\u0430\u043b", "year": "2015-2019", "country": " \u0421\u0428\u0410", "genre": " \u0422\u0440\u0438\u043b\u043b\u0435\u0440\u044b"}, "data-id": "9364", "url": "https://rezka.ag/series/thriller/9364-mister-robot-2015.html"}, "quality": "", "dorl": "", "download_type": 1, "translator_id": "56", "status": "run", "run_season": 2, "run_episode": 5} \ No newline at end of file diff --git a/main.py b/main.py index ef6e2b4..c4da0bd 100644 --- a/main.py +++ b/main.py @@ -3,6 +3,8 @@ if History().status == 'run' and input('Continue[yN]?') != "n": movie_data = History().movie_data else: + History().status = "end" + search_text = input('Поиск: ') search_result = Search(search_text) @@ -24,7 +26,7 @@ quality = input("Введите качество: ") else: dorl = "d" - quality = "1080p]" + quality = "1080" downloader = Download(download_data, dorl, quality) @@ -43,7 +45,10 @@ History().download_type = download_type if download_type == 1: - season = int(input('Введите номер сезона: ')) + if History().status == 'run' and History().download_type == 1 and History().run_season !="": + season = History().run_season + else: + season = int(input('Введите номер сезона: ')) downloader.download_season(season) print('Скачивание успешно завершено!') elif download_type == 2: @@ -55,7 +60,7 @@ end = episodes_count while not correct_episode: try: - downloader.download_episodes(season, start, end) + downloader.download_episodes(season, start) correct_episode = True except EpisodeNumberIsOutOfRange: print('Неверный диапазон!') @@ -77,10 +82,8 @@ elif download_type == 4: downloader.download_all_serial() print('Скачивание успешно завершено!') - if dorl == "pls": - downloader.convert_to_pls() - - - else: print('Неверный тип скачивания!') + if dorl == "pls": + downloader.convert_to_pls() + History().status = "end" From 8f081f1302ce1c6281d2fdef73e3d7f632597663 Mon Sep 17 00:00:00 2001 From: Oleh Shvets Date: Thu, 21 Mar 2024 01:46:37 +0100 Subject: [PATCH 15/21] 'HDRezkaAPI: remove dorl parameter from Download class, update history.json with new movie data, and minor changes in main.py' --- HDRezkaAPI/download.py | 46 ++++++++++++++---------------------------- main.py | 7 ++----- 2 files changed, 17 insertions(+), 36 deletions(-) diff --git a/HDRezkaAPI/download.py b/HDRezkaAPI/download.py index 817e8ef..b0101bf 100644 --- a/HDRezkaAPI/download.py +++ b/HDRezkaAPI/download.py @@ -1,7 +1,5 @@ import sys -import os from os import path -from bs4 import BeautifulSoup from .request import Request from .get_stream import GetStream from .history import History @@ -24,22 +22,18 @@ class EpisodeNumberIsOutOfRange(Error): class Download: - def __init__(self, download_data, dorl, quality): + def __init__(self, download_data, quality): self.data = download_data self.quality = quality - self.dorl = dorl self.url = download_data['url'] - response = Request().get(self.url) - self.soup = BeautifulSoup(response.content, 'html.parser') - # self.favs = self.soup.find('input', id='ctrl_favs').get('value') self.name = download_data['url'].split('/')[-1].split('.')[0] - if self.dorl == "pls": - self.filee = open(f"{self.name}.list", "w") if self.data['translations_list']: self.translator_id = self.__get_translation() - # if download_data["seasons_episodes_count"] == 0: - # self.translator_id = self.__get_translation() + if download_data.get("seasons_episodes_count") == 0: + # If there are no seasons and episodes + print("select again:") + self.translator_id = self.__get_translation() else: self.translator_id = self.__detect_translation() @@ -89,9 +83,8 @@ def download_episodes(self, season, start): # TODO Make new custom exception for incorrect season number and realize it return - episodes_list = self.soup.find( - 'ul', id=f'simple-episodes-list-{season}') - episodes_count = len(episodes_list.findAll('li')) + episodes_count = self.data['seasons_episodes_count'][season] + if end > episodes_count or start < 0: raise EpisodeNumberIsOutOfRange @@ -123,8 +116,6 @@ def download_episode(self, season, episode): stream_url = GetStream().get_series_stream(data) downloaded_folder = self.name - if self.dorl != "pls": - os.makedirs(downloaded_folder, exist_ok=True) season = str(season).zfill(2) episode = str(episode).zfill(2) file_name = f"{downloaded_folder}/s{season}e{episode}.mp4" @@ -148,7 +139,6 @@ def download_movie(self): stream_url = GetStream().get_movie_stream(data) # TODO Fix file name bug - # file_name = f"test.mp4" download_data = { 'stream_url': stream_url, @@ -161,12 +151,6 @@ def download_movie(self): def __download( download_data): if download_data['stream_url']: print (download_data['file_name']) - # if self.dorl == "pls": - # self.filee.write(download_data['stream_url'] + "\n") - - # if self.data['type'] == 'movie': - # os.system(f"bomi {download_data['stream_url']}") - # else: History().status = "run" fullpath = path.join(path.curdir, download_data['file_name']) @@ -212,13 +196,13 @@ def __get_translation(self) -> int: return translation_id - def __detect_translation(self): - if self.data['type'] == 'movie': - event_type = 'initCDNMoviesEvents' - else: - event_type = 'initCDNSeriesEvents' + # def __detect_translation(self): + # if self.data['type'] == 'movie': + # event_type = 'initCDNMoviesEvents' + # else: + # event_type = 'initCDNSeriesEvents' - tmp = str(self.soup).split(f"sof.tv.{event_type}")[-1].split("{")[0] - translator_id = tmp.split(",")[1].strip() + # tmp = str(self.soup).split(f"sof.tv.{event_type}")[-1].split("{")[0] + # translator_id = tmp.split(",")[1].strip() - return translator_id + # return translator_id diff --git a/main.py b/main.py index c4da0bd..785d7dc 100644 --- a/main.py +++ b/main.py @@ -22,13 +22,11 @@ print (f'\n{download_data}\n') if 0: - dorl = input('PLS?') quality = input("Введите качество: ") else: - dorl = "d" quality = "1080" -downloader = Download(download_data, dorl, quality) +downloader = Download(download_data, quality) print(movie_info) @@ -84,6 +82,5 @@ print('Скачивание успешно завершено!') else: print('Неверный тип скачивания!') - if dorl == "pls": - downloader.convert_to_pls() + History().status = "end" From 16f67f509461026a018f6a44c2c2be461567368d Mon Sep 17 00:00:00 2001 From: Oleh Shvets Date: Thu, 21 Mar 2024 02:14:23 +0100 Subject: [PATCH 16/21] Change downloaded file path to be in a subdirectory; create the subdirectory if it does not exist * In `Download.download_episode`, change the `downloaded_folder` variable to `f"../{self.name}"` to download the file to a subdirectory with the name of the series. * Add `os.makedirs(downloaded_folder, exist_ok=True)` to create the subdirectory if it does not already exist. * In the same function, change `fullpath` to use `os.path.join(os.path.curdir, download_data['file_name'])` instead of `path.join(path.curdir, download_data['file_name'])`. --- lol.py | 70 ---------------------------------------------------------- 1 file changed, 70 deletions(-) delete mode 100644 lol.py diff --git a/lol.py b/lol.py deleted file mode 100644 index 843b3a2..0000000 --- a/lol.py +++ /dev/null @@ -1,70 +0,0 @@ -enable -conf ter -vlan 10 - name v10 -vlan 20 - name v20 -vlan 30 - name v30 - - import os -import pathlib -import sys -import asyncio -import aiohttp -from tqdm import tqdm -from requests import Request - -class MultiDownload: - def __init__(self, data, dorl): - self.data = data - self.dorl = dorl - self.filee = open("download_links.txt", "w") - - async def download(self, download_data): - if download_data['stream_url']: - print (download_data['file_name']) - if self.dorl == "pls": - self.filee.write(download_data['stream_url'] + "\n") - - if self.data['type'] == 'movie': - os.system(f"bomi {download_data['stream_url']}") - else: - fullpath = pathlib.Path.cwd() / download_data['file_name'] - - async with aiohttp.ClientSession() as session: - async with session.get(download_data['stream_url']) as r: - total_size = int(r.headers.get('content-length', 0)) - with open(fullpath, "wb") as f, tqdm( - unit="B", - unit_scale=True, - unit_divisor=1024, - total=total_size, - file=sys.stdout, - desc=download_data['file_name'] - ) as progress: - while True: - chunk = await r.content.read(4096) - if not chunk: - break - datasize = f.write(chunk) - progress.update(datasize) - - async def download_all(self): - tasks = [self.download(download_data) for download_data in self.data['download_data']] - await asyncio.gather(*tasks) - - def start(self): - asyncio.run(self.download_all()) - -# Example usage -data = { - 'type': 'movie', - 'download_data': [ - {'file_name': 'file1.mp4', 'stream_url': 'https://example.com/file1.mp4'}, - {'file_name': 'file2.mp4', 'stream_url': 'https://example.com/file2.mp4'}, - ] -} - -multi_download = MultiDownload(data, dorl="pls") -multi_download.start() \ No newline at end of file From 08f0a7b1823176a5f7625ca04c2b1555f5a205e2 Mon Sep 17 00:00:00 2001 From: Oleh Shvets Date: Thu, 21 Mar 2024 02:14:29 +0100 Subject: [PATCH 17/21] mmm --- HDRezkaAPI/download.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/HDRezkaAPI/download.py b/HDRezkaAPI/download.py index b0101bf..0465626 100644 --- a/HDRezkaAPI/download.py +++ b/HDRezkaAPI/download.py @@ -1,5 +1,5 @@ import sys -from os import path +import os from .request import Request from .get_stream import GetStream from .history import History @@ -115,7 +115,10 @@ def download_episode(self, season, episode): History().run_episode = episode stream_url = GetStream().get_series_stream(data) - downloaded_folder = self.name + downloaded_folder = f"../{self.name}" + # downloaded_folder = self.name + os.makedirs(downloaded_folder, exist_ok=True) + season = str(season).zfill(2) episode = str(episode).zfill(2) file_name = f"{downloaded_folder}/s{season}e{episode}.mp4" @@ -152,7 +155,7 @@ def __download( download_data): if download_data['stream_url']: print (download_data['file_name']) History().status = "run" - fullpath = path.join(path.curdir, download_data['file_name']) + fullpath = os.path.join(os.path.curdir, download_data['file_name']) with Request().get(download_data['stream_url'], stream=True) as r, open(fullpath, "wb") as f, tqdm( unit="B", From 15f8c79f725bf257364253805048786ce8538a6c Mon Sep 17 00:00:00 2001 From: Oleh Shvets Date: Sun, 21 Apr 2024 22:03:17 +0200 Subject: [PATCH 18/21] Change in Download class to include quality in file name The diff includes changes to the `download.py` file which modifies the `Download` class to include the quality of the video in the file name. Additionally, the default quality has --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index ae1b7a9..bea8fd1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ venv .idea HDRezkaAPI/__pycache__ -*.mp4 \ No newline at end of file +*.mp4 +*.json \ No newline at end of file From 3ba3e947534f03b45d3cc722df5bd75621a00f3f Mon Sep 17 00:00:00 2001 From: Oleh Shvets Date: Sun, 21 Apr 2024 23:23:52 +0200 Subject: [PATCH 19/21] Update download.py to include quality in file name and use ThreadPoolExecutor for downloading; update history.json with new movie data The diff includes changes to the download.py file to update the file name to include the quality of the --- HDRezkaAPI/NEWdOWN.py | 38 ++++++++++++++++++++++++++++++++++++++ HDRezkaAPI/download.py | 5 +++-- history.json | 22 +++++++++++++++++++++- main.py | 2 +- 4 files changed, 63 insertions(+), 4 deletions(-) create mode 100644 HDRezkaAPI/NEWdOWN.py mode change 100644 => 100755 HDRezkaAPI/download.py mode change 100644 => 100755 history.json mode change 100644 => 100755 main.py diff --git a/HDRezkaAPI/NEWdOWN.py b/HDRezkaAPI/NEWdOWN.py new file mode 100644 index 0000000..f30ad68 --- /dev/null +++ b/HDRezkaAPI/NEWdOWN.py @@ -0,0 +1,38 @@ +import sys +import os +import requests +from tqdm import tqdm +# from .history import History +from concurrent.futures import ThreadPoolExecutor + +def download_file(download_data): + if download_data['stream_url']: + print(download_data['file_name']) + fullpath = os.path.join(os.path.curdir, download_data['file_name']) + + # Send HEAD request to get file size + response = requests.head(download_data['stream_url']) + total_size = int(response.headers.get('content-length', 0)) + + # Download the file using GET request + with requests.get(download_data['stream_url'], stream=True) as r: + with open(fullpath, "wb") as f, tqdm( + unit="B", + unit_scale=True, + unit_divisor=1024, + total=total_size, + file=sys.stdout, + desc=download_data['file_name'] + ) as progress: + for chunk in r.iter_content(chunk_size=1024*4): + if chunk: + datasize = f.write(chunk) + progress.update(datasize) + +data = { + "stream_url": "https://stream.voidboost.cc/6fac7ad9ce36bdd25731bbca2a92e3c7:2024042219:QXlQUFEyYnNlVzBZOExha1Z0YVdHYUV3NVVrTXhGU2VYaXY0ZFBtLzhmL2lYcHprMVFJbXJKM0ZhS0VsMGtyMXcrOHJKSkg3Syt2djRsWEhYL1oyS2c9PQ==/1/3/5/0/1/1/7kqf9.mp4", + + 'file_name': 'test.mp4' + + } +download_file(data) diff --git a/HDRezkaAPI/download.py b/HDRezkaAPI/download.py old mode 100644 new mode 100755 index 0465626..50882ac --- a/HDRezkaAPI/download.py +++ b/HDRezkaAPI/download.py @@ -121,7 +121,7 @@ def download_episode(self, season, episode): season = str(season).zfill(2) episode = str(episode).zfill(2) - file_name = f"{downloaded_folder}/s{season}e{episode}.mp4" + file_name = f"{downloaded_folder}/s{season}e{episode}-{self.quality}.mp4" download_data = { 'stream_url': stream_url, @@ -154,6 +154,7 @@ def download_movie(self): def __download( download_data): if download_data['stream_url']: print (download_data['file_name']) + print (download_data['stream_url']) History().status = "run" fullpath = os.path.join(os.path.curdir, download_data['file_name']) @@ -165,7 +166,7 @@ def __download( download_data): file=sys.stdout, desc=download_data['file_name'] ) as progress: - for chunk in r.iter_content(chunk_size=4096): + for chunk in r.iter_content(chunk_size=1024*4): if chunk: datasize = f.write(chunk) progress.update(datasize) diff --git a/history.json b/history.json old mode 100644 new mode 100755 index bd6d92e..2536b6c --- a/history.json +++ b/history.json @@ -1 +1,21 @@ -{"movie_data": {"id": 23, "name": "\u041c\u0438\u0441\u0442\u0435\u0440 \u0420\u043e\u0431\u043e\u0442", "info": {"type": "\u0421\u0435\u0440\u0438\u0430\u043b", "year": "2015-2019", "country": " \u0421\u0428\u0410", "genre": " \u0422\u0440\u0438\u043b\u043b\u0435\u0440\u044b"}, "data-id": "9364", "url": "https://rezka.ag/series/thriller/9364-mister-robot-2015.html"}, "quality": "", "dorl": "", "download_type": 1, "translator_id": "56", "status": "run", "run_season": 2, "run_episode": 5} \ No newline at end of file +{ + "movie_data": { + "id": 1, + "name": "\u042d\u0442\u043e \u043c\u044b", + "info": { + "type": "\u0421\u0435\u0440\u0438\u0430\u043b", + "year": "2016-2022", + "country": " \u0421\u0428\u0410", + "genre": " \u0414\u0440\u0430\u043c\u044b" + }, + "data-id": "19545", + "url": "https://rezka.ag/series/drama/19545-eto-my-2016.html" + }, + "quality": "", + "dorl": "", + "download_type": 1, + "translator_id": "232", + "status": "run", + "run_season": 1, + "run_episode": 1 +} \ No newline at end of file diff --git a/main.py b/main.py old mode 100644 new mode 100755 index 785d7dc..956ab1f --- a/main.py +++ b/main.py @@ -24,7 +24,7 @@ if 0: quality = input("Введите качество: ") else: - quality = "1080" + quality = "720" downloader = Download(download_data, quality) From 760296eb68c2518b88a4ff0891e85dfdbec1c353 Mon Sep 17 00:00:00 2001 From: Oleh Shvets Date: Tue, 16 Jul 2024 18:07:39 +0200 Subject: [PATCH 20/21] "Updated download.py to access run_season as an attribute instead of a method, and modified history.json with new movie data." --- HDRezkaAPI/download.py | 2 +- HDRezkaAPI/main.ipynb | 110 +++++++++++++++++++++++++++++++++++++++++ history.json | 22 +-------- 3 files changed, 112 insertions(+), 22 deletions(-) create mode 100644 HDRezkaAPI/main.ipynb mode change 100755 => 100644 history.json diff --git a/HDRezkaAPI/download.py b/HDRezkaAPI/download.py index 50882ac..ffdeb7f 100755 --- a/HDRezkaAPI/download.py +++ b/HDRezkaAPI/download.py @@ -44,7 +44,7 @@ def download_all_serial(self): while not correct_season: try: if History().status == 'run' and History().run_season !="": - season = History().run_season() + season = History().run_season self.download_seasons(season, seasons_count +1) else: for season in range(1, seasons_count + 1): diff --git a/HDRezkaAPI/main.ipynb b/HDRezkaAPI/main.ipynb new file mode 100644 index 0000000..8554934 --- /dev/null +++ b/HDRezkaAPI/main.ipynb @@ -0,0 +1,110 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "ename": "ImportError", + "evalue": "attempted relative import with no known parent package", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mImportError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[1], line 3\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01msys\u001b[39;00m\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mos\u001b[39;00m\n\u001b[0;32m----> 3\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mrequest\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Request\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mget_stream\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m GetStream\n\u001b[1;32m 5\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mhistory\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m History\n", + "\u001b[0;31mImportError\u001b[0m: attempted relative import with no known parent package" + ] + } + ], + "source": [ + "import sys\n", + "import os\n", + "from .request import Request\n", + "from .get_stream import GetStream\n", + "from .history import History\n", + "from tqdm import tqdm\n", + "from concurrent.futures import ThreadPoolExecutor" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def download_chunk(url, chunk_size=4096):\n", + " with Request().get(url, stream=True) as r:\n", + " chunk = r.iter_content(chunk_size=chunk_size)\n", + " return b\"\".join(chunk)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def download_file(url, file_path, num_threads=4):\n", + " with ThreadPoolExecutor(max_workers=num_threads) as executor:\n", + " response = Request().head(url)\n", + " total_size = int(response.headers.get('content-length', 0))\n", + "\n", + " with open(file_path, \"wb\") as f:\n", + " futures = []\n", + " for i in range(0, total_size, chunk_size * num_threads):\n", + " futures.append(executor.submit(download_chunk, url, chunk_size))\n", + " for future in futures:\n", + " f.write(future.result())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def __download( download_data):\n", + " if download_data['stream_url']:\n", + " print (download_data['file_name'])\n", + " History().status = \"run\"\n", + " fullpath = os.path.join(os.path.curdir, download_data['file_name'])\n", + "\n", + " with Request().get(download_data['stream_url'], stream=True) as r, open(fullpath, \"wb\") as f, tqdm(\n", + " unit=\"B\",\n", + " unit_scale=True,\n", + " unit_divisor=1024,\n", + " total=int(r.headers.get('content-length', 0)),\n", + " file=sys.stdout,\n", + " desc=download_data['file_name']\n", + " ) as progress:\n", + " for chunk in r.iter_content(chunk_size=4096):\n", + " if chunk:\n", + " datasize = f.write(chunk)\n", + " progress.update(datasize)\n", + " History().run_episode = History().run_episode + 1" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.12" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/history.json b/history.json old mode 100755 new mode 100644 index 2536b6c..00ca414 --- a/history.json +++ b/history.json @@ -1,21 +1 @@ -{ - "movie_data": { - "id": 1, - "name": "\u042d\u0442\u043e \u043c\u044b", - "info": { - "type": "\u0421\u0435\u0440\u0438\u0430\u043b", - "year": "2016-2022", - "country": " \u0421\u0428\u0410", - "genre": " \u0414\u0440\u0430\u043c\u044b" - }, - "data-id": "19545", - "url": "https://rezka.ag/series/drama/19545-eto-my-2016.html" - }, - "quality": "", - "dorl": "", - "download_type": 1, - "translator_id": "232", - "status": "run", - "run_season": 1, - "run_episode": 1 -} \ No newline at end of file +{"movie_data": {"id": 1, "name": "\u0411\u0430\u0448\u043d\u044f \u0411\u043e\u0433\u0430", "info": {"type": "\u0410\u043d\u0438\u043c\u0435", "year": "2020", "country": " \u042f\u043f\u043e\u043d\u0438\u044f", "genre": " \u041f\u0440\u0438\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f"}, "data-id": "35561", "url": "https://rezka.ag/animation/adventures/35561-bashnya-boga-2020.html"}, "quality": "", "dorl": "", "download_type": 4, "translator_id": "19", "status": "run", "run_season": 1, "run_episode": 10} \ No newline at end of file From 6b7edf0878a15e58b37808a1de275e1b9234057a Mon Sep 17 00:00:00 2001 From: Oleh Shvets Date: Sun, 25 May 2025 13:25:14 +0200 Subject: [PATCH 21/21] Enhance README.md with detailed project description, features, installation instructions, usage guidelines, and project structure. This update provides users with comprehensive information on how to utilize the HDRezkaTool effectively. --- README.md | 84 ++++++++++++++++++++++++++++++++++++++++++++++-- requirements.txt | 3 ++ 2 files changed, 84 insertions(+), 3 deletions(-) create mode 100644 requirements.txt diff --git a/README.md b/README.md index e1c7684..4eca25a 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,85 @@ # HDRezkaTool -To add HDRezla libery use +A powerful Python tool for downloading movies and TV series from HDRezka. This tool provides a convenient command-line interface to search, browse, and download content with various quality options. + +## Features + +- 🔍 Search functionality for movies and TV series +- 🎬 Support for both movies and TV series downloads +- 📺 Multiple download options for TV series: + - Download entire season + - Download specific episodes + - Download multiple seasons + - Download complete series +- 🎥 Quality selection (720p by default) +- 📝 Download history tracking +- 🔄 Resume interrupted downloads +- 🌐 Russian language interface + +## Installation + +1. Clone the repository: +```bash +git clone https://github.com/yourusername/HDRezkaTool.git +cd HDRezkaTool +``` + +2. Install the required dependencies: ```bash -cp -r HDRezkaAPI /usr/lib/python3/dist-packages/ -pip install tqdm bs4 +pip install -r requirements.txt ``` + +## Usage + +1. Run the main script: +```bash +python main.py +``` + +2. Follow the interactive prompts: + - Enter search query + - Select content from search results + - Choose download options + - Select quality (default: 720p) + +### Download Options for TV Series + +1. Download a single season: + - Select option 1 + - Enter season number + +2. Download specific episodes: + - Select option 2 + - Enter season number + - Enter starting episode number + +3. Download multiple seasons: + - Select option 3 + - Enter starting season number + - Enter ending season number + +4. Download complete series: + - Select option 4 + +## Project Structure + +``` +HDRezkaTool/ +├── HDRezkaAPI/ # Core API implementation +├── main.py # Main application script +├── history.json # Download history +├── LICENSE # Project license +└── README.md # This file +``` + +## Contributing + +Contributions are welcome! Please feel free to submit a Pull Request. + +## License + +This project is licensed under the terms of the license included in the LICENSE file. + +## Disclaimer + +This tool is for educational purposes only. Please respect copyright laws and the terms of service of the source website. The developers are not responsible for any misuse of this tool. diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..83853b2 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +tqdm>=4.65.0 +beautifulsoup4>=4.12.0 +requests>=2.31.0 \ No newline at end of file