Rewrite hls downloader

This commit is contained in:
Lovi 2024-10-17 18:21:59 +02:00
parent 45660f7a02
commit e3ddf7a00d
58 changed files with 777 additions and 1966 deletions

View File

@ -63,11 +63,11 @@ sudo chmod +x unix_install.sh && ./unix_install.sh
Run the script with the following command:
#### On Windows:
```powershell
.\run.py
python .\run.py
```
or
```powershell
.venv\Scripts\python .\run.py
source .venv/bin/activate && python run.py && deactivate
```
#### On Linux/MacOS/BSD:
@ -257,9 +257,8 @@ The `run-container` command mounts also the `config.json` file, so any change to
<a id="tutorial"></a>
## Tutorial 📖
For a detailed walkthrough, refer to the [video tutorial](https://www.youtube.com/watch?v=Ok7hQCgxqLg&ab_channel=Nothing)
Add [api_1](https://www.youtube.com/watch?v=3ylBSMyQlhM)
Add [api_2](https://www.youtube.com/watch?v=ReEYUIbdbG4)
[win]("https://www.youtube.com/watch?v=mZGqK4wdN-k")
[linux]("https://www.youtube.com/watch?v=0qUNXPE_mTg")
<a id="to-do"></a>
## To do 📝

View File

@ -1,9 +1,5 @@
# 02.07.24
import sys
import logging
# External libraries
import httpx
from bs4 import BeautifulSoup

View File

@ -26,7 +26,6 @@ from ..Template.Class.SearchType import MediaItem
from .costant import ROOT_PATH, DOMAIN_NOW, SITE_NAME, MOVIE_FOLDER
def download_title(select_title: MediaItem):
"""
Downloads a media item and saves it as an MP4 file.
@ -62,4 +61,4 @@ def download_title(select_title: MediaItem):
manager = TOR_downloader()
manager.add_magnet_link(final_url)
manager.start_download()
manager.move_downloaded_files(mp4_path)
manager.move_downloaded_files(mp4_path)

View File

@ -1,6 +1,5 @@
# 19.06.24
import sys
import logging
from typing import List

View File

@ -1,7 +1,6 @@
# 19.06.24
import sys
import logging
# Internal utilities
@ -85,4 +84,4 @@ def get_select_title(table_show_manager, media_search_manager):
else:
console.print("\n[red]Wrong index")
sys.exit(0)
sys.exit(0)

View File

@ -1,7 +1,6 @@
# 26.05.24
import re
import sys
import logging
@ -175,4 +174,3 @@ class VideoSource:
except Exception as e:
logging.error(f"An error occurred: {e}")
return None

View File

@ -20,7 +20,6 @@ from ..Template.Class.SearchType import MediaItem
# Config
from .costant import ROOT_PATH, SITE_NAME, MOVIE_FOLDER
def download_film(select_title: MediaItem):
"""
@ -57,4 +56,4 @@ def download_film(select_title: MediaItem):
HLS_Downloader(
m3u8_playlist = master_playlist,
output_filename = os.path.join(mp4_path, mp4_name)
).start()
).start()

View File

@ -1,9 +1,5 @@
# 26.05.24
import sys
import logging
# External libraries
import httpx
from bs4 import BeautifulSoup
@ -23,7 +19,6 @@ media_search_manager = MediaManager()
table_show_manager = TVShowManager()
def title_search(title_search: str) -> int:
"""
Search for titles based on a search query.
@ -68,4 +63,4 @@ def run_get_select_title():
"""
Display a selection of titles and prompt the user to choose one.
"""
return get_select_title(table_show_manager, media_search_manager)
return get_select_title(table_show_manager, media_search_manager)

View File

@ -1,6 +1,5 @@
# 01.03.24
import sys
import logging
from urllib.parse import urljoin, urlparse, parse_qs, urlencode, urlunparse

View File

@ -13,6 +13,7 @@ from .anime import download_film, download_series
indice = 1
_deprecate = False
def search():
# Make request to site to get content that corrsisponde to that string
@ -34,4 +35,4 @@ def search():
console.print(f"\n[red]Nothing matching was found for[white]: [purple]{string_to_search}")
# Retry
search()
search()

View File

@ -23,7 +23,6 @@ from .costant import ROOT_PATH, SITE_NAME, SERIES_FOLDER, MOVIE_FOLDER
video_source = VideoSource()
def download_episode(index_select: int):
"""
Downloads the selected episode.

View File

@ -1,9 +1,5 @@
# 01.07.24
import sys
import logging
# External libraries
import httpx
from bs4 import BeautifulSoup
@ -26,7 +22,6 @@ media_search_manager = MediaManager()
table_show_manager = TVShowManager()
def title_search(word_to_search: str) -> int:
"""
Search for titles based on a search query.
@ -69,4 +64,4 @@ def run_get_select_title():
"""
Display a selection of titles and prompt the user to choose one.
"""
return get_select_title(table_show_manager, media_search_manager)
return get_select_title(table_show_manager, media_search_manager)

View File

@ -48,4 +48,4 @@ def download_title(select_title: MediaItem):
manager = TOR_downloader()
manager.add_magnet_link(select_title.url)
manager.start_download()
manager.move_downloaded_files(mp4_path)
manager.move_downloaded_files(mp4_path)

View File

@ -1,7 +1,6 @@
# 05.07.24
import re
import sys
import logging

View File

@ -1,9 +1,5 @@
# 03.07.24
import sys
import logging
# External libraries
import httpx
from bs4 import BeautifulSoup
@ -69,4 +65,4 @@ def run_get_select_title():
"""
Display a selection of titles and prompt the user to choose one.
"""
return get_select_title(table_show_manager, media_search_manager)
return get_select_title(table_show_manager, media_search_manager)

View File

@ -24,7 +24,6 @@ from ..costant import COOKIE
class GetSerieInfo:
def __init__(self, dict_serie: MediaItem) -> None:
"""
Initializes the GetSerieInfo object with default values.
@ -49,7 +48,6 @@ class GetSerieInfo:
List[Dict[str, str]]: List of dictionaries containing episode information.
"""
# Make an HTTP request to the series URL
try:
response = httpx.get(self.url + "?area=online", cookies=self.cookies, headers=self.headers, timeout=10)
response.raise_for_status()

View File

@ -1,6 +1,5 @@
# 14.06.24
import sys
import logging

View File

@ -1,6 +1,5 @@
# 13.06.24
import sys
import logging
from typing import List, Dict
@ -20,7 +19,6 @@ from ...Template.Class.SearchType import MediaItem
class GetSerieInfo:
def __init__(self, dict_serie: MediaItem) -> None:
"""
Initializes the GetSerieInfo object with default values.

View File

@ -1,7 +1,6 @@
# 26.05.24
import re
import sys
import logging

View File

@ -70,4 +70,4 @@ def run_get_select_title():
"""
Display a selection of titles and prompt the user to choose one.
"""
return get_select_title(table_show_manager, media_search_manager)
return get_select_title(table_show_manager, media_search_manager)

View File

@ -13,13 +13,12 @@ from bs4 import BeautifulSoup
# Internal utilities
from Src.Util.message import start_message
from Src.Util.console import console
from Src.Util.os import create_folder, can_create_file, remove_special_characters
from Src.Util.os import can_create_file, remove_special_characters
from Src.Util.headers import get_headers
from Src.Lib.Downloader import HLS_Downloader
# Logic class
from ..Template.Class.SearchType import MediaItem
from ..guardaserie.Player.supervideo import VideoSource
from Src.Lib.TMBD import Json_film
@ -47,9 +46,14 @@ def download_film(movie_details: Json_film):
response.raise_for_status()
# Extract supervideo url
soup = BeautifulSoup(response.text, "html.parser")
player_links = soup.find("ul", class_ = "_player-mirrors").find_all("li")
supervideo_url = "https:" + player_links[0].get("data-link")
try:
soup = BeautifulSoup(response.text, "html.parser")
player_links = soup.find("ul", class_ = "_player-mirrors").find_all("li")
supervideo_url = "https:" + player_links[0].get("data-link")
except:
logging.error("Not found in the server.")
sys.exit(0)
# Set domain and media ID for the video source
video_source = VideoSource()

View File

@ -223,5 +223,3 @@ class VideoSource:
final_url = urlunparse(new_url) # Construct the final URL from the modified parts
return final_url

View File

@ -1,60 +0,0 @@
# 03.03.24
from typing import Dict, Any, List
class Episode:
def __init__(self, data: Dict[str, Any]):
self.title: int = data.get('title', '')
self.url: str = data.get('link', '')
def __str__(self):
return f"Episode(title='{self.title}')"
class EpisodeManager:
def __init__(self):
self.episodes: List[Episode] = []
def add_episode(self, episode_data: Dict[str, Any]):
"""
Add a new episode to the manager.
Parameters:
- episode_data (Dict[str, Any]): A dictionary containing data for the new episode.
"""
episode = Episode(episode_data)
self.episodes.append(episode)
def get(self, index: int) -> Episode:
"""
Get an episode by its index.
Parameters:
- index (int): Index of the episode to retrieve.
Returns:
Episode: The episode object.
"""
return self.episodes[index]
def get_length(self) -> int:
"""
Get the number of episodes in the manager.
Returns:
int: Number of episodes.
"""
return len(self.episodes)
def clear(self) -> None:
"""
This method clears the episodes list.
Parameters:
- self: The object instance.
"""
self.episodes.clear()
def __str__(self):
return f"EpisodeManager(num_episodes={len(self.episodes)})"

View File

@ -1,56 +0,0 @@
# 03.03.24
from typing import List, Dict, Union
class Season:
def __init__(self, season_data: Dict[str, Union[int, str, None]]):
self.name: str = season_data.get('name')
def __str__(self):
return f"Season(name='{self.name}')"
class SeasonManager:
def __init__(self):
self.seasons: List[Season] = []
def add_season(self, season_data: Dict[str, Union[int, str, None]]):
"""
Add a new season to the manager.
Parameters:
- season_data (Dict[str, Union[int, str, None]]): A dictionary containing data for the new season.
"""
season = Season(season_data)
self.seasons.append(season)
def get(self, index: int) -> Season:
"""
Get a season item from the list by index.
Parameters:
- index (int): The index of the seasons item to retrieve.
Returns:
- Season: The media item at the specified index.
"""
return self.media_list[index]
def get_length(self) -> int:
"""
Get the number of seasons in the manager.
Returns:
- int: Number of seasons.
"""
return len(self.seasons)
def clear(self) -> None:
"""
This method clears the seasons list.
"""
self.seasons.clear()
def __str__(self):
return f"SeasonManager(num_seasons={len(self.seasons)})"

View File

@ -1,263 +0,0 @@
# 30.06.24
import time
import logging
# External library
from bs4 import BeautifulSoup
from seleniumbase import Driver
# Internal utilities
from Src.Util._jsonConfig import config_manager
# Config
USE_HEADLESS = config_manager.get_bool("BROWSER", "headless")
class DownloadAutomation:
def __init__(self, download_link):
self.download_link = download_link
self.driver = Driver(uc=True, uc_cdp_events=True, headless=USE_HEADLESS)
self.mp4_link = None
def run(self):
"""
Executes the entire automation process.
"""
try:
self.driver.get(self.download_link)
self._inject_css()
self._observe_title_change()
self._bypass_page_1()
self._bypass_page_2_verify_button()
self._bypass_page_2_two_steps_btn()
self._wait_for_document_complete()
self._wait_for_bypass_completion()
self._extract_download_link()
except Exception as e:
logging.error(f"Error occurred during automation: {str(e)}")
finally:
self.quit()
def _inject_css(self):
"""
Injects CSS to make all elements on the page invisible.
"""
try:
css_script = """
const voidCSS = `* {opacity: 0;z-index: -999999;}`;
function addStyle(css) {
let head = document.querySelector('head'),
style = document.createElement('style');
style.innerHTML = css;
head.appendChild(style);
}
"""
self.driver.execute_script(css_script)
logging.info("CSS injected.")
time.sleep(0.4)
except Exception as e:
logging.error(f"Error injecting CSS: {str(e)}")
def _observe_title_change(self):
"""
Observes changes in the document title and applies CSS injection.
"""
try:
observer_script = """
let headObserver = new MutationObserver(function() {
if (document.title) {
addStyle(voidCSS.replace(';', ' !important;'));
headObserver.disconnect();
}
});
headObserver.observe(document.documentElement, {childList: true, subtree: true});
"""
self.driver.execute_script(observer_script)
logging.info("Title observer set.")
time.sleep(0.4)
except Exception as e:
logging.error(f"Error setting title observer: {str(e)}")
def _bypass_page_1(self):
"""
Executes action to bypass Page 1.
"""
try:
action1_script = """
function action1() {
try {
document.querySelector('#landing').submit();
document.title = "Bypass Action (1/3)";
} catch {}
}
action1();
"""
self.driver.execute_script(action1_script)
logging.info("Page 1 bypassed.")
time.sleep(0.4)
except Exception as e:
logging.error(f"Error bypassing Page 1: {str(e)}")
def _bypass_page_2_verify_button(self):
"""
Executes action to bypass Page 2 by clicking on verify_button.
"""
try:
action2_script = """
function action2() {
try {
document.querySelector('#verify_button').click();
document.title = "Bypass Action (2/3)";
} catch {}
}
action2();
"""
self.driver.execute_script(action2_script)
logging.info("Page 2 bypassed.")
time.sleep(0.4)
except Exception as e:
logging.error(f"Error bypassing Page 2: {str(e)}")
def _bypass_page_2_two_steps_btn(self):
"""
Executes action to bypass Page 2 by waiting for and clicking two_steps_btn.
"""
try:
action3_script = """
function action3() {
try {
let observer = new MutationObserver(function() {
if (document.querySelector('#two_steps_btn').href !== "") {
observer.disconnect();
document.title = "Bypass Action (3/3)";
window.location = document.querySelector('#two_steps_btn').href;
}
});
observer.observe(document.querySelector('#two_steps_btn'), {attributes: true});
} catch {}
}
action3();
"""
self.driver.execute_script(action3_script)
logging.info("Page 2 bypassed with observation and redirect.")
time.sleep(0.4)
except Exception as e:
logging.error(f"Error bypassing Page 2 with observation: {str(e)}")
def _wait_for_document_complete(self):
"""
Waits for the document to be completely loaded to execute actions.
"""
try:
onreadystatechange_script = """
document.onreadystatechange = function () {
if (document.readyState === 'complete') {
action1();
action2();
action3();
}
}
"""
self.driver.execute_script(onreadystatechange_script)
logging.info("onreadystatechange set.")
time.sleep(0.4)
except Exception as e:
logging.error(f"Error setting onreadystatechange: {str(e)}")
def _wait_for_bypass_completion(self):
"""
Waits for the bypass process to complete.
"""
try:
while True:
if ".mkv" in self.driver.title or ".mp4" in self.driver.title:
logging.info("Bypass completed.")
break
time.sleep(0.5)
except Exception as e:
logging.error(f"Error waiting for bypass completion: {str(e)}")
def _extract_download_link(self):
"""
Extracts the final download link after bypassing and loads the download page.
"""
try:
final_html = self.driver.page_source
soup = BeautifulSoup(final_html, 'html.parser')
video_link = soup.find("a", class_="btn").get('href')
logging.info("Loading download page.")
self.driver.get(video_link)
logging.info(f"Download page link: {video_link}")
except Exception as e:
logging.error(f"Error extracting download link: {str(e)}")
def capture_url(self, req):
"""
Function to capture url in background
"""
try:
url = req['params']['documentURL']
# Filter for mp4 video download
if "googleusercontent" in str(url):
self.mp4_link = url
except:
pass
def quit(self):
"""
Quits the WebDriver instance.
"""
try:
logging.info("Removing ad headers.")
css_script = """
const voidCSS = ``;
function addStyle(css) {
let head = document.querySelector('head'),
style = document.createElement('style');
style.innerHTML = css;
head.appendChild(style);
}
"""
self.driver.execute_script(css_script)
self.driver.add_cdp_listener("*", lambda data: self.capture_url(data))
time.sleep(0.3)
logging.info("Clicking button.")
self.driver.execute_script("document.getElementById('ins').click();")
while True:
time.sleep(0.3)
if self.mp4_link is not None:
break
logging.info(f"MP4 Link: {self.mp4_link}")
logging.info("Quitting...")
self.driver.quit()
except Exception as e:
logging.error(f"Error during quitting: {str(e)}")

View File

@ -1,230 +0,0 @@
# 29.06.24
import re
import httpx
import logging
from bs4 import BeautifulSoup
# Logic class
from ..Class.EpisodeType import EpisodeManager
from ..Class.SeriesType import SeasonManager
class EpisodeScraper:
def __init__(self, url):
"""
The constructor for the EpisodeScraper class.
Parameters:
- url (str): The URL of the webpage to scrape.
"""
self.url = url
self.soup = self._get_soup()
self.info_site = self._extract_info()
self.stagioni = self._organize_by_season()
def _get_soup(self):
"""
Retrieves and parses the webpage content using BeautifulSoup.
Returns:
- BeautifulSoup: The parsed HTML content of the webpage.
"""
try:
response = httpx.get(self.url)
response.raise_for_status()
return BeautifulSoup(response.text, 'html.parser')
except Exception as e:
print(f"Error fetching the URL: {e}")
raise
def _extract_info(self):
"""
Extracts the episode information from the parsed HTML.
Returns:
- list: A list of dictionaries containing episode information.
"""
rows = self.soup.find_all("p", style="text-align: center;")
info_site = []
# Loop through each <p> tag and extract episode information
for i, row in enumerate(rows, start=1):
episodes = []
# Find all <a> tags with the specified class and extract title and link
for episode in row.find_all("a", class_="maxbutton-2"):
episodes.append({
'title': episode.text,
'link': episode.get('href')
})
# If there are episodes, add them to the info_site list
if len(episodes) > 0:
if i == 2:
title_name = rows[i-1].get_text().split("\n")[3]
if "Epis" not in str(title_name):
info_site.append({
'name': title_name,
'episode': episodes,
})
else:
title_name = rows[i-2].get_text()
if "Epis" not in str(title_name):
info_site.append({
'name': title_name,
'episode': episodes,
})
# For only episode
if len(info_site) == 0:
for i, row in enumerate(rows, start=1):
for episode in row.find_all("a", class_="maxbutton-1"):
info_site.append({
'name': rows[i-1].get_text().split("\n")[1],
'url': episode.get("href"),
})
# Get only fist quality
break
break
return info_site
def _organize_by_season(self):
"""
Organizes the extracted information into seasons.
Returns:
- dict: A dictionary organizing episodes by season.
"""
stagioni = {}
# Loop through each episode dictionary and organize by season
for dizionario in self.info_site:
nome = dizionario["name"]
# Use regex to search for season numbers (S01, S02, etc.)
match = re.search(r'S\d+', nome)
if match:
stagione = match.group(0)
if stagione not in stagioni:
stagioni[stagione] = []
stagioni[stagione].append(dizionario)
self.is_serie = len(list(stagioni.keys())) > 0
return stagioni
def get_available_seasons(self):
"""
Returns a list of available seasons.
Returns:
- list: A list of available seasons.
"""
return list(self.stagioni.keys())
def get_episodes_by_season(self, season):
"""
Returns a list of episodes for a given season.
Parameters:
- season (str): The season identifier (e.g., 'S01').
Returns:
- list: A list of episodes for the specified season.
"""
episodes = self.stagioni[season][0]['episode']
def find_group_size(episodes):
seen_titles = {}
for index, episode in enumerate(episodes):
title = episode["title"]
if title in seen_titles:
return index - seen_titles[title]
seen_titles[title] = index
return len(episodes)
# Find group size
group_size = find_group_size(episodes)
grouped_episodes = []
start_index = 0
while start_index < len(episodes):
group = episodes[start_index:start_index + group_size]
grouped_episodes.append(group)
start_index += group_size
return grouped_episodes[0]
def get_film(self):
"""
Retrieves the first element from the info_site list.
"""
return self.info_site[0]
class ApiManager:
def __init__(self, url):
"""
The constructor for the EpisodeScraper class.
Parameters:
- url (str): The URL of the webpage to scrape.
"""
self.url = url
self.episode_scraper = EpisodeScraper(url)
self.is_serie = self.episode_scraper.is_serie
self.obj_season_manager: SeasonManager = SeasonManager()
self.obj_episode_manager: EpisodeManager = EpisodeManager()
def collect_season(self):
"""
Collect available seasons from the webpage and add them to the season manager.
"""
available_seasons = self.episode_scraper.get_available_seasons()
for dict_season in available_seasons:
self.obj_season_manager.add_season({'name': dict_season})
def collect_episode(self, season_name):
"""
Collect episodes for a given season and add them to the episode manager.
Parameters:
- season_name (str): The name of the season for which to collect episodes.
"""
dict_episodes = self.episode_scraper.get_episodes_by_season(season_name)
for dict_episode in dict_episodes:
self.obj_episode_manager.add_episode(dict_episode)
def get_film_playlist(self):
"""
Get the film playlist from the episode scraper.
Returns:
- list: A list of films in the playlist.
"""
return self.episode_scraper.get_film()

View File

@ -1,39 +0,0 @@
# 09.06.24
# Internal utilities
from Src.Util.console import console, msg
# Logic class
from .site import title_search, run_get_select_title
from .serie import download_serie
# Variable
indice = 6
_deprecate = True
def search():
"""
Main function of the application for film and series.
"""
# Make request to site to get content that corrsisponde to that string
string_to_search = msg.ask("\n[purple]Insert word to search in all site").strip()
len_database = title_search(string_to_search)
if len_database > 0:
# Select title from list
select_title = run_get_select_title()
# Download only TV
download_serie(select_title)
else:
console.print(f"\n[red]Nothing matching was found for[white]: [purple]{string_to_search}")
# Retry
search()

View File

@ -1,15 +0,0 @@
# 09.06.24
import os
# Internal utilities
from Src.Util._jsonConfig import config_manager
SITE_NAME = os.path.basename(os.path.dirname(os.path.abspath(__file__)))
ROOT_PATH = config_manager.get('DEFAULT', 'root_path')
DOMAIN_NOW = config_manager.get_dict('SITE', SITE_NAME)['domain']
SERIES_FOLDER = "Serie"
MOVIE_FOLDER = "Film"

View File

@ -1,58 +0,0 @@
# 23.08.24
# 3.12.23
import os
import sys
import logging
from urllib.parse import urlparse
# Internal utilities
from Src.Util.console import console
from Src.Util.message import start_message
from Src.Util.os import create_folder, remove_special_characters
from Src.Lib.Downloader import MP4_downloader
# Logic class
from .Core.Player.driveleech import DownloadAutomation
# Variable
from .costant import ROOT_PATH, SITE_NAME, MOVIE_FOLDER
def download_film(name: str, url: str):
"""
Downloads a film using the provided url.
Parameters:
- name (str): Name of the film
- url (str): MP4 url of the film
"""
# Start message and display film information
start_message()
console.print(f"[yellow]Download: [red]{name} \n")
# Construct the MP4 file name and path
mp4_path = os.path.join(ROOT_PATH, SITE_NAME, MOVIE_FOLDER, remove_special_characters(name))
# Ensure the folder path exists
create_folder(mp4_path)
# Parse start page url
downloder_vario = DownloadAutomation(url)
downloder_vario.run()
downloder_vario.quit()
# Parse mp4 link
mp4_final_url = downloder_vario.mp4_link
parsed_url = urlparse(mp4_final_url)
MP4_downloader(
url = mp4_final_url,
path = os.path.join(mp4_path, "film_0.mp4"),
referer = f"{parsed_url.scheme}://{parsed_url.netloc}/",
)

View File

@ -1,204 +0,0 @@
# 29.06.24
import os
import sys
import logging
from urllib.parse import urlparse
# Internal utilities
from Src.Util.console import console, msg
from Src.Util.message import start_message
from Src.Util.os import create_folder, can_create_file
from Src.Util.table import TVShowManager
from Src.Lib.Downloader import MP4_downloader
from ..Template import manage_selection, map_episode_title, validate_selection, validate_episode_selection
# Logic class
from .Core.Player.episode_scraper import ApiManager
from .Core.Player.driveleech import DownloadAutomation
from ..Template.Class.SearchType import MediaItem
from .film import download_film
# Variable
from .costant import ROOT_PATH, SITE_NAME, SERIES_FOLDER
table_show_manager = TVShowManager()
def download_video(api_manager: ApiManager, index_season_selected: int, index_episode_selected: int) -> None:
"""
Download a single episode video.
Parameters:
- tv_name (str): Name of the TV series.
- index_season_selected (int): Index of the selected season.
- index_episode_selected (int): Index of the selected episode.
"""
start_message()
# Get info about episode
obj_episode = api_manager.obj_episode_manager.episodes[index_episode_selected - 1]
tv_name = api_manager.obj_season_manager.seasons[index_season_selected - 1].name
console.print(f"[yellow]Download: [red]{index_season_selected}:{index_episode_selected} {obj_episode.title}")
print()
# Define filename and path for the downloaded video
mp4_name = f"{map_episode_title(tv_name, index_season_selected, index_episode_selected, obj_episode.title)}.mp4"
mp4_path = os.path.join(ROOT_PATH, SITE_NAME, SERIES_FOLDER, tv_name, f"S{index_season_selected}")
# Check if can create file output
create_folder(mp4_path)
if not can_create_file(mp4_name):
logging.error("Invalid mp4 name.")
sys.exit(0)
# Parse start page url
start_message()
downloder_vario = DownloadAutomation(obj_episode.url)
downloder_vario.run()
downloder_vario.quit()
# Parse mp4 link
mp4_final_url = downloder_vario.mp4_link
parsed_url = urlparse(mp4_final_url)
MP4_downloader(
url = mp4_final_url,
path = os.path.join(mp4_path, mp4_name),
referer = f"{parsed_url.scheme}://{parsed_url.netloc}/",
)
def download_episode(api_manager: ApiManager, index_season_selected: int, download_all: bool = False) -> None:
"""
Download all episodes of a season.
Parameters:
- tv_name (str): Name of the TV series.
- index_season_selected (int): Index of the selected season.
- download_all (bool): Download all seasons episodes
"""
# Clean memory of all episodes and get the number of the season (some dont follow rule of [1,2,3,4,5] but [1,2,3,145,5,6,7]).
api_manager.obj_episode_manager.clear()
season_name = api_manager.obj_season_manager.seasons[index_season_selected-1].name
# Collect all best episode
start_message()
api_manager.collect_episode(season_name)
episodes_count = api_manager.obj_episode_manager.get_length()
if download_all:
# Download all episodes without asking
for i_episode in range(1, episodes_count + 1):
download_video(api_manager, index_season_selected, i_episode)
console.print(f"\n[red]End downloaded [yellow]season: [red]{index_season_selected}.")
else:
# Display episodes list and manage user selection
last_command = display_episodes_list()
list_episode_select = manage_selection(last_command, episodes_count)
try:
list_episode_select = validate_episode_selection(list_episode_select, episodes_count)
except ValueError as e:
console.print(f"[red]{str(e)}")
return
# Download selected episodes
for i_episode in list_episode_select:
download_video(api_manager, index_season_selected, i_episode)
def download_serie(media: MediaItem):
"""
Downloads a media title using its API manager and WebAutomation driver.
Parameters:
media (MediaItem): The media item to be downloaded.
"""
start_message()
# Initialize the API manager with the media and driver
api_manager = ApiManager(media.url)
# Collect information about seasons
api_manager.collect_season()
seasons_count = api_manager.obj_season_manager.get_length()
if seasons_count > 0:
# Prompt user for season selection and download episodes
console.print(f"\n[green]Seasons found: [red]{seasons_count}")
index_season_selected = msg.ask(
"\n[cyan]Insert season number [yellow](e.g., 1), [red]* [cyan]to download all seasons, "
"[yellow](e.g., 1-2) [cyan]for a range of seasons, or [yellow](e.g., 3-*) [cyan]to download from a specific season to the end"
)
# Manage and validate the selection
list_season_select = manage_selection(index_season_selected, seasons_count)
try:
list_season_select = validate_selection(list_season_select, seasons_count)
except ValueError as e:
console.print(f"[red]{str(e)}")
return
# Loop through the selected seasons and download episodes
for i_season in list_season_select:
if len(list_season_select) > 1 or index_season_selected == "*":
# Download all episodes if multiple seasons are selected or if '*' is used
download_episode(api_manager, i_season, download_all=True)
else:
# Otherwise, let the user select specific episodes for the single season
download_episode(api_manager, i_season, download_all=False)
else:
# If not seasons find is a film
obj_film = api_manager.episode_scraper.info_site[0]
download_film(obj_film.get('name'), obj_film.get('url'))
def display_episodes_list(api_manager: ApiManager) -> str:
"""
Display episodes list and handle user input.
Returns:
last_command (str): Last command entered by the user.
"""
# Set up table for displaying episodes
table_show_manager.set_slice_end(10)
# Add columns to the table
column_info = {
"Index": {'color': 'red'},
"Name": {'color': 'magenta'},
}
table_show_manager.add_column(column_info)
# Populate the table with episodes information
for i, media in enumerate(api_manager.obj_episode_manager.episodes):
table_show_manager.add_tv_show({
'Index': str(i),
'Name': media.title
})
# Run the table and handle user input
last_command = table_show_manager.run()
if last_command == "q":
console.print("\n[red]Quit [white]...")
sys.exit(0)
return last_command

View File

@ -1,70 +0,0 @@
# 09.06.24
import logging
# External libraries
import httpx
from bs4 import BeautifulSoup
from unidecode import unidecode
# Internal utilities
from Src.Util.table import TVShowManager
from ..Template import search_domain, get_select_title
# Logic class
from ..Template.Class.SearchType import MediaManager
# Variable
from .costant import SITE_NAME
media_search_manager = MediaManager()
table_show_manager = TVShowManager()
def title_search(word_to_search: str) -> int:
"""
Search for titles based on a search query.
Parameters:
- title_search (str): The title to search for.
Returns:
- int: The number of titles found.
"""
# Create a web automation driver instance
domain_to_use, _ = search_domain(SITE_NAME, f"https://{SITE_NAME}")
# Construct the full site URL and load the search page
response = httpx.get(f"https://{SITE_NAME}.{domain_to_use}/search/{unidecode(word_to_search)}")
response.raise_for_status()
# Retrieve and parse the HTML content of the page
soup = BeautifulSoup(response.text, "html.parser")
table_content = soup.find_all("article")
# Iterate through the search results to find relevant titles
for title in table_content:
# Construct a media object with the title's details
obj = {
'url': title.find("a").get("href"),
'name': title.find("a").get("title"),
}
# Add the media object to the media search manager
media_search_manager.add_media(obj)
# Return the number of titles found
return media_search_manager.get_length()
def run_get_select_title():
"""
Display a selection of titles and prompt the user to choose one.
"""
return get_select_title(table_show_manager, media_search_manager)

View File

@ -1,84 +0,0 @@
# 29.06.24
import sys
import logging
import json
import urllib.parse
# Logic class
from ...Template.Class.SearchType import MediaItem
from Src.Lib.Driver import WebAutomation
# Variable
from ..costant import SITE_NAME, DOMAIN_NOW
full_site_name=f"{SITE_NAME}.{DOMAIN_NOW}"
class ApiManager:
def __init__(self, media: MediaItem, main_driver: WebAutomation) -> None:
"""
Initializes the ApiManager with a media item and a web automation driver.
Parameters:
- media (MediaItem): The media item to be processed.
- main_driver (WebAutomation): The driver to perform web automation tasks.
"""
self.media = media
self.id = self.media.url.split("/")[-1]
self.main_driver = main_driver
def get_playlist(self) -> str:
"""
Retrieves the URL of the best quality stream available for the media item.
Returns:
- str: The URL of the best quality stream.
"""
# Prepare the JSON payload
# !! NOTE: MISSING ALL OTHER PLAYER
json_payload = {
"0": {
"json": {
"type": self.media.type,
"id": self.id,
"provider": "showbox-internal"
}
}
}
# Convert the payload to a JSON string and properly escape it
json_string = json.dumps (json_payload)
encoded_json_string = urllib.parse.quote(json_string)
# Format the URL with the encoded JSON string
api_url = f"https://{full_site_name}/api/trpc/provider.run?batch=1&input={encoded_json_string}"
# Load the API URL in the web driver
self.main_driver.get_page(str(api_url))
# Retrieve and parse the page content
soup = self.main_driver.retrieve_soup()
content = soup.find("pre").text
if "error" in str(content):
logging.error("Failed to make request. Work in progress to add all other provider ...")
# TO DO !!! ADD ALL OTHER PROVIDER
sys.exit(0)
data = json.loads(content)[0]['result']['data']['json']['stream'][0]['qualities']
# Return the URL based on the available quality
if len(data.keys()) == 1:
return data.get('360')['url']
if len(data.keys()) == 2:
return data.get("720")['url']
if len(data.keys()) == 3:
return data.get('1080')['url']
if len(data.keys()) == 4:
return data.get('4k')['url']

View File

@ -1,47 +0,0 @@
# 09.06.24
import sys
import logging
# Internal utilities
from Src.Util.console import console, msg
# Logic class
from .site import title_search, run_get_select_title
from .film import download_film
# Variable
indice = 5
_deprecate = True
# !! NOTE: 23.08.24 Seleniumbase cant bypass site
def search():
"""
Main function of the application for film and series.
"""
# Make request to site to get content that corrsisponde to that string
string_to_search = msg.ask("\n[purple]Insert word to search in all site").strip()
len_database, main_driver = title_search(string_to_search)
if len_database > 0:
# Select title from list
select_title = run_get_select_title()
if select_title.type == "movie":
download_film(select_title, main_driver)
else:
logging.error(f"Not supported: {select_title.type}")
sys.exit(0)
else:
console.print(f"\n[red]Nothing matching was found for[white]: [purple]{string_to_search}")
# Retry
search()

View File

@ -1,20 +0,0 @@
# 09.06.24
import os
# Internal utilities
from Src.Util._jsonConfig import config_manager
SITE_NAME = os.path.basename(os.path.dirname(os.path.abspath(__file__)))
ROOT_PATH = config_manager.get('DEFAULT', 'root_path')
DOMAIN_NOW = config_manager.get_dict('SITE', SITE_NAME)['domain']
SERIES_FOLDER = "Serie"
MOVIE_FOLDER = "Film"
# Fix site name for .
# URL => https://watch.lonelil.ru
SITE_NAME = SITE_NAME.replace("_", ".")

View File

@ -1,65 +0,0 @@
# 29.06.24
import os
import sys
import logging
from urllib.parse import urlparse
# Internal utilities
from Src.Util.message import start_message
from Src.Util.os import create_folder, can_create_file, remove_special_characters
from Src.Lib.Downloader import MP4_downloader
# Logic class
from .Player.lonelil import ApiManager
from ..Template.Class.SearchType import MediaItem
from Src.Lib.Driver import WebAutomation
# Variable
from .costant import ROOT_PATH, SITE_NAME, SERIES_FOLDER
def download_film(media: MediaItem, main_driver: WebAutomation):
"""
Downloads a media title using its API manager and WebAutomation driver.
Parameters:
- media (MediaItem): The media item to be downloaded.
- main_driver (WebAutomation): The web automation driver instance.
"""
start_message()
# Initialize the API manager with the media and driver
api_manager = ApiManager(media, main_driver)
# Get the URL of the media playlist
url_playlist = api_manager.get_playlist()
# Construct the MP4 file name and path
mp4_name = remove_special_characters(media.name) + ".mp4"
mp4_path = os.path.join(ROOT_PATH, SITE_NAME, SERIES_FOLDER, remove_special_characters(media.name))
# Ensure the folder path exists
create_folder(mp4_path)
# Check if the MP4 file can be created
if not can_create_file(mp4_name):
logging.error("Invalid mp4 name.")
sys.exit(0)
# Parse the URL of the playlist
parsed_url = urlparse(url_playlist)
# Quit the main driver instance
main_driver.quit()
# Initiate the MP4 downloader with necessary parameters
MP4_downloader(
url=url_playlist,
path=os.path.join(mp4_path, mp4_name),
referer=f"{parsed_url.scheme}://{parsed_url.netloc}/",
)

View File

@ -1,68 +0,0 @@
# 09.06.24
import logging
# External libraries
from unidecode import unidecode
# Internal utilities
from Src.Util.table import TVShowManager
from Src.Lib.Driver import WebAutomation
from ..Template import search_domain, get_select_title
# Logic class
from ..Template.Class.SearchType import MediaManager
# Variable
from .costant import SITE_NAME, DOMAIN_NOW
media_search_manager = MediaManager()
table_show_manager = TVShowManager()
def title_search(word_to_search: str) -> int:
"""
Search for titles based on a search query.
Parameters:
- title_search (str): The title to search for.
Returns:
int: The number of titles found.
"""
# Create a web automation driver instance
main_driver = WebAutomation()
# Construct the full site URL and load the search page
full_site_name = f"{SITE_NAME}.{DOMAIN_NOW}"
main_driver.get_page(f"https://{full_site_name}/search?q={unidecode(word_to_search)}")
# Retrieve and parse the HTML content of the page
soup = main_driver.retrieve_soup()
content_table = soup.find_all("a")
# Iterate through the search results to find relevant titles
for title in content_table:
if any(keyword in str(title).lower() for keyword in ["show/", "movie/", "anime/"]):
obj = {
'url': f"https://{full_site_name}" + title.get("href"),
'name': title.find("img").get("alt"),
'type': title.find_all("p")[-1].get_text().split("·")[0].strip().lower()
}
media_search_manager.add_media(obj)
# Return the number of titles found
return media_search_manager.get_length(), main_driver
def run_get_select_title():
"""
Display a selection of titles and prompt the user to choose one.
"""
return get_select_title(table_show_manager, media_search_manager)

View File

@ -1,3 +0,0 @@
# 20.02.24
from .downloader import HLS_Downloader

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,6 @@
import os
import sys
import time
import logging
from concurrent.futures import ThreadPoolExecutor

View File

@ -14,7 +14,6 @@ from concurrent.futures import ThreadPoolExecutor
# External libraries
import httpx
from httpx import HTTPTransport
from tqdm import tqdm
@ -82,17 +81,6 @@ class M3U8_Segments:
# Server ip
self.fake_proxy = False
def add_server_ip(self, list_ip: list):
"""
Add server IP addresses
Args:
list_ip (list): A list of IP addresses to be added.
"""
if list_ip is not None:
self.fake_proxy = True
self.fake_proxy_ip = list_ip
def __get_key__(self, m3u8_parser: M3U8_Parser) -> bytes:
"""
Retrieves the encryption key from the M3U8 playlist.
@ -289,7 +277,7 @@ class M3U8_Segments:
progress_bar.update(1)
except Exception as e:
console.print(f"Failed download: '{ts_url}' with error: {e}")
console.print(f"\nFailed to download: '{ts_url}' with error: {e}")
def write_segments_to_file(self):
"""

View File

@ -1,3 +0,0 @@
# 23.06.24
from .downloader import MP4_downloader

View File

@ -1,3 +0,0 @@
# 23.06.24
from .downloader import TOR_downloader

View File

@ -207,4 +207,4 @@ class TOR_downloader:
break
self.qb.delete_permanently(self.qb.torrents()[-1]['hash'])
return True
return True

View File

@ -1,5 +1,5 @@
# 23.06.24
from .HLS import HLS_Downloader
from .MP4 import MP4_downloader
from .TOR import TOR_downloader
from .HLS.downloader import HLS_Downloader
from .MP4.downloader import MP4_downloader
from .TOR.downloader import TOR_downloader

View File

@ -1,3 +0,0 @@
# 29.06.24
from .driver_1 import WebAutomation

View File

@ -1,7 +1,6 @@
# 17.09.24
import json
from typing import List, Dict, Optional
from typing import Dict
class Json_film:

View File

@ -1,3 +0,0 @@
# 01.03.24
from .update import update

View File

@ -19,6 +19,7 @@ def get_call_stack():
- script (str): The name of the script file containing the function.
- line (int): The line number in the script where the function is defined.
"""
stack = inspect.stack()
call_stack = []

View File

@ -17,4 +17,4 @@ class Colors:
LIGHT_MAGENTA = "\033[95m"
LIGHT_CYAN = "\033[96m"
WHITE = "\033[97m"
RESET = "\033[0m"
RESET = "\033[0m"

View File

@ -3,8 +3,9 @@
from rich.console import Console
from rich.prompt import Prompt, Confirm
from rich.panel import Panel
from rich.table import Table
# Variable
msg = Prompt()
console = Console()
console = Console()

View File

@ -2,7 +2,6 @@
import re
import random
import logging
# External library

View File

@ -44,4 +44,4 @@ def start_message():
console.print(f"[magenta]Created by: Lovi\n")
row = "-" * console.width
console.print(f"[yellow]{row} \n")
console.print(f"[yellow]{row} \n")

View File

@ -17,15 +17,16 @@ import contextlib
import urllib.request
import importlib.metadata
# External library
import httpx
import unicodedata
# Internal utilities
from .console import console
# --> OS FILE ASCII
special_chars_to_remove = [
'!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '[', ']', '{', '}', '<',
@ -34,7 +35,6 @@ special_chars_to_remove = [
]
def get_max_length_by_os(system: str) -> int:
"""
Determines the maximum length for a base name based on the operating system.

View File

@ -2,7 +2,6 @@
from rich.console import Console
from rich.table import Table
from rich.text import Text
from rich.prompt import Prompt
from rich.style import Style
from typing import Dict, List, Any

7
Test/manual_config.json Normal file
View File

@ -0,0 +1,7 @@
{
"site": "",
"string_search": "",
"serie": true,
"season_cmd": "",
"episode_cmd": ""
}

View File

@ -8,13 +8,13 @@
"root_path": "Video",
"map_episode_name": "%(tv_name)_S%(season)E%(episode)_%(episode_name)",
"config_qbit_tor": {
"host": "192.168.1.125",
"host": "192.168.1.58",
"port": "8080",
"user": "admin",
"pass": "adminadmin"
},
"not_close": false,
"show_trending": true
"show_trending": false
},
"REQUESTS": {
"timeout": 10,

1
run.py
View File

@ -1,4 +1,3 @@
#!
# 10.12.23
import os

View File

@ -1,169 +1,134 @@
@echo off
:: BatchGotAdmin
::-------------------------------------
REM --> Check for permissions
>nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"
REM --> If error flag set, we do not have admin.
if '%errorlevel%' NEQ '0' (
echo Requesting administrative privileges...
goto UACPrompt
) else ( goto gotAdmin )
:UACPrompt
echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
set params = %*:"="
echo UAC.ShellExecute "cmd.exe", "/c %~s0 %params%", "", "runas", 1 >> "%temp%\getadmin.vbs"
"%temp%\getadmin.vbs"
del "%temp%\getadmin.vbs"
exit /B
:gotAdmin
pushd "%CD%"
CD /D "%~dp0"
::--------------------------------------
REM Check if running in PowerShell
@REM Check and install python
@REM where /q python >nul 2>nul
@REM if %errorlevel% neq 1 (
@REM echo Checking Python...
@REM ) else (
@REM call (exit /b 0)
@REM echo python not found. Checking for Chocolatey...
@REM REM Check if Chocolatey is installed
@REM where /q choco >nul 2>nul
@REM if %errorlevel% neq 1 (
@REM echo Installing python using Chocolatey...
@REM choco install python -y
@REM ) else (
@REM echo Chocolatey is not installed.
@REM echo Please install Chocolatey first from https://chocolatey.org/install
@REM echo After installing Chocolatey, you can run this script again to install ffmpeg.
@REM echo Alternatively, you can install python manually from https://www.python.org/
@REM exit /b 1
@REM )
@REM )
REM Get the Python version
for /f "delims=" %%v in ('python -c "import sys; print('.'.join(map(str, sys.version_info[:3])))"') do set PYTHON_VERSION=%%v
REM Set the required version
set REQUIRED_VERSION=3.8
REM Compare the Python version with the required version
REM Split versions by dot and compare each segment
setlocal enabledelayedexpansion
for /f "tokens=1-3 delims=." %%a in ("%PYTHON_VERSION%") do (
set PYTHON_MAJOR=%%a
set PYTHON_MINOR=%%b
set PYTHON_PATCH=%%c
:: Controlla se lo script è in esecuzione come amministratore
net session >nul 2>&1
if %errorlevel% neq 0 (
echo Eseguendo come amministratore...
:: Riavvia lo script con privilegi di amministratore
powershell -Command "Start-Process '%~f0' -Verb RunAs"
exit /b
)
for /f "tokens=1-3 delims=." %%a in ("%REQUIRED_VERSION%") do (
set REQUIRED_MAJOR=%%a
set REQUIRED_MINOR=%%b
set REQUIRED_PATCH=%%c
)
chcp 65001 > nul
SETLOCAL ENABLEDELAYEDEXPANSION
REM Compare major version
if !PYTHON_MAJOR! LSS !REQUIRED_MAJOR! (
echo ERROR: Python version !PYTHON_VERSION! is < !REQUIRED_VERSION!. Exiting...
exit /b 1
) else if !PYTHON_MAJOR! EQU !REQUIRED_MAJOR! (
REM Compare minor version
if !PYTHON_MINOR! LSS !REQUIRED_MINOR! (
echo ERROR: Python version !PYTHON_VERSION! is < !REQUIRED_VERSION!. Exiting...
exit /b 1
) else if !PYTHON_MINOR! EQU !REQUIRED_MINOR! (
REM Compare patch version
if !PYTHON_PATCH! LSS !REQUIRED_PATCH! (
echo ERROR: Python version !PYTHON_VERSION! is < !REQUIRED_VERSION!. Exiting...
exit /b 1
)
)
)
echo Inizio dello script...
echo Python version %PYTHON_VERSION% is >= %REQUIRED_VERSION%. Continuing...
if exist ".venv\" (
echo .venv exists. Installing requirements.txt.
.venv\Scripts\python -m pip install -r requirements.txt
) else (
echo Making .venv and installing requirements.txt...
python -m venv .venv
.venv\Scripts\python -m pip install -r requirements.txt
)
where /q ffmpeg >nul 2>nul
if %errorlevel% neq 1 (
echo ffmpeg exists.
) else (
call (exit /b 0)
echo ffmpeg not found. Checking for Chocolatey...
REM Check if Chocolatey is installed
where /q choco >nul 2>nul
if %errorlevel% neq 1 (
echo Installing ffmpeg using Chocolatey...
choco install ffmpeg -y
) else (
echo Chocolatey is not installed.
echo Please install Chocolatey first from https://chocolatey.org/install
echo After installing Chocolatey, you can run this script again to install ffmpeg.
echo Alternatively, you can install ffmpeg manually from https://www.ffmpeg.org/
:: Controlla se Chocolatey è già installato
:check_choco
echo Verifica se Chocolatey è installato...
choco --version >nul 2>&1
IF %ERRORLEVEL% EQU 0 (
echo Chocolatey è già installato. Salto l'installazione.
goto install_python
) ELSE (
echo Installazione di Chocolatey...
@"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" || (
echo Errore durante l'installazione di Chocolatey.
exit /b 1
)
echo Chocolatey installato con successo.
call choco --version
echo.
)
REM Check if OpenSSL exists
where /q openssl >nul 2>nul
if %errorlevel% neq 1 (
echo openssl exists.
goto end
)
call (exit /b 0)
REM Check if pycryptodome is installed
.venv\Scripts\pip list | findstr /i "pycryptodome" >nul
if %errorlevel% equ 0 (
echo pycryptodome exists.
goto end
)
call (exit /b 0)
REM Prompt for installation option
echo Please choose an option:
echo 1) openssl
echo 2) pycryptodome
set /p choice="Enter your choice (1): "
REM Handle the choice
if "%choice%"=="2" (
echo Installing pycryptodome.
.venv\Scripts\pip install pycryptodome
) else (
echo Installing openssl.
echo Checking for Chocolatey...
REM Check if Chocolatey is installed
where /q choco >nul 2>nul
if %errorlevel% neq 1 (
echo Installing openssl using Chocolatey...
choco install openssl -y
) else (
echo Chocolatey is not installed.
echo Please install Chocolatey first from https://chocolatey.org/install
echo After installing Chocolatey, you can run this script again to install openssl.
echo Alternatively, you can install OpenSSH manually from https://www.openssl.com/.
:: Controlla se Python è già installato
:install_python
echo Verifica se Python è installato...
python -V >nul 2>&1
IF %ERRORLEVEL% EQU 0 (
echo Python è già installato. Salto l'installazione.
goto install_openssl
) ELSE (
echo Installazione di Python...
choco install python --confirm --params="'/NoStore'" --allow-downgrade || (
echo Errore durante l'installazione di Python.
exit /b 1
)
echo Python installato con successo.
call python -V
echo.
)
:end
setlocal enabledelayedexpansion & set "tempfile=%temp%\tempfile.txt" & (echo #^^!.venv\Scripts\python & type run.py | more +1) > "!tempfile!" & move /Y "!tempfile!" run.py >nul 2>nul
echo Everything is installed^^!
echo Run StreamingCommunity with '.\run.py'
:: Chiedi di riavviare il terminale
echo Si prega di riavviare il terminale per continuare...
pause
exit /b
:: Controlla se OpenSSL è già installato
:install_openssl
echo Verifica se OpenSSL è installato...
openssl version -a >nul 2>&1
IF %ERRORLEVEL% EQU 0 (
echo OpenSSL è già installato. Salto l'installazione.
goto install_ffmpeg
) ELSE (
echo Installazione di OpenSSL...
choco install openssl --confirm || (
echo Errore durante l'installazione di OpenSSL.
exit /b 1
)
echo OpenSSL installato con successo.
call openssl version -a
echo.
)
:: Controlla se FFmpeg è già installato
:install_ffmpeg
echo Verifica se FFmpeg è installato...
ffmpeg -version >nul 2>&1
IF %ERRORLEVEL% EQU 0 (
echo FFmpeg è già installato. Salto l'installazione.
goto create_venv
) ELSE (
echo Installazione di FFmpeg...
choco install ffmpeg --confirm || (
echo Errore durante l'installazione di FFmpeg.
exit /b 1
)
echo FFmpeg installato con successo.
call ffmpeg -version
echo.
)
:: Verifica delle installazioni
:verifica_installazioni
echo Verifica delle installazioni...
call choco --version
call python -V
call openssl version -a
call ffmpeg -version
echo Tutti i programmi sono stati installati e verificati con successo.
:: Crea un ambiente virtuale .venv
:create_venv
echo Verifica se l'ambiente virtuale .venv esiste già...
if exist .venv (
echo L'ambiente virtuale .venv esiste già. Salto la creazione.
) ELSE (
echo Creazione dell'ambiente virtuale .venv...
python -m venv .venv || (
echo Errore durante la creazione dell'ambiente virtuale.
exit /b 1
)
echo Ambiente virtuale creato con successo.
)
:: Attiva l'ambiente virtuale e installa i requisiti
echo Installazione dei requisiti...
call .venv\Scripts\activate.bat
pip install -r requirements.txt || (
echo Errore durante l'installazione dei requisiti.
exit /b 1
)
:: Esegui run.py
echo Esecuzione di run.py...
call .venv\Scripts\python .\run.py || (
echo Errore durante l'esecuzione di run.py.
exit /b 1
)
echo Fine dello script.
ENDLOCAL