mirror of
https://github.com/Arrowar/StreamingCommunity.git
synced 2025-06-05 02:55:25 +00:00
Rewrite hls downloader
This commit is contained in:
parent
45660f7a02
commit
e3ddf7a00d
@ -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 📝
|
||||
|
@ -1,9 +1,5 @@
|
||||
# 02.07.24
|
||||
|
||||
import sys
|
||||
import logging
|
||||
|
||||
|
||||
# External libraries
|
||||
import httpx
|
||||
from bs4 import BeautifulSoup
|
||||
|
@ -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)
|
||||
|
@ -1,6 +1,5 @@
|
||||
# 19.06.24
|
||||
|
||||
import sys
|
||||
import logging
|
||||
|
||||
from typing import List
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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)
|
||||
|
@ -1,6 +1,5 @@
|
||||
# 01.03.24
|
||||
|
||||
import sys
|
||||
import logging
|
||||
from urllib.parse import urljoin, urlparse, parse_qs, urlencode, urlunparse
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -1,7 +1,6 @@
|
||||
# 05.07.24
|
||||
|
||||
import re
|
||||
import sys
|
||||
import logging
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
|
@ -1,6 +1,5 @@
|
||||
# 14.06.24
|
||||
|
||||
import sys
|
||||
import logging
|
||||
|
||||
|
||||
|
@ -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.
|
||||
|
@ -1,7 +1,6 @@
|
||||
# 26.05.24
|
||||
|
||||
import re
|
||||
import sys
|
||||
import logging
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
|
@ -223,5 +223,3 @@ class VideoSource:
|
||||
final_url = urlunparse(new_url) # Construct the final URL from the modified parts
|
||||
|
||||
return final_url
|
||||
|
||||
|
@ -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)})"
|
@ -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)})"
|
@ -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)}")
|
@ -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()
|
@ -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()
|
@ -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"
|
@ -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}/",
|
||||
)
|
@ -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
|
@ -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)
|
@ -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']
|
@ -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()
|
@ -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("_", ".")
|
@ -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}/",
|
||||
)
|
@ -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)
|
@ -1,3 +0,0 @@
|
||||
# 20.02.24
|
||||
|
||||
from .downloader import HLS_Downloader
|
File diff suppressed because it is too large
Load Diff
@ -2,7 +2,6 @@
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import logging
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
|
||||
|
@ -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):
|
||||
"""
|
||||
|
@ -1,3 +0,0 @@
|
||||
# 23.06.24
|
||||
|
||||
from .downloader import MP4_downloader
|
@ -1,3 +0,0 @@
|
||||
# 23.06.24
|
||||
|
||||
from .downloader import TOR_downloader
|
@ -207,4 +207,4 @@ class TOR_downloader:
|
||||
break
|
||||
|
||||
self.qb.delete_permanently(self.qb.torrents()[-1]['hash'])
|
||||
return True
|
||||
return True
|
||||
|
@ -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
|
@ -1,3 +0,0 @@
|
||||
# 29.06.24
|
||||
|
||||
from .driver_1 import WebAutomation
|
@ -1,7 +1,6 @@
|
||||
# 17.09.24
|
||||
|
||||
import json
|
||||
from typing import List, Dict, Optional
|
||||
from typing import Dict
|
||||
|
||||
|
||||
class Json_film:
|
||||
|
@ -1,3 +0,0 @@
|
||||
# 01.03.24
|
||||
|
||||
from .update import update
|
@ -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 = []
|
||||
|
||||
|
@ -17,4 +17,4 @@ class Colors:
|
||||
LIGHT_MAGENTA = "\033[95m"
|
||||
LIGHT_CYAN = "\033[96m"
|
||||
WHITE = "\033[97m"
|
||||
RESET = "\033[0m"
|
||||
RESET = "\033[0m"
|
||||
|
@ -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()
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
import re
|
||||
import random
|
||||
import logging
|
||||
|
||||
|
||||
# External library
|
||||
|
@ -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")
|
||||
|
@ -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.
|
||||
|
@ -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
7
Test/manual_config.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"site": "",
|
||||
"string_search": "",
|
||||
"serie": true,
|
||||
"season_cmd": "",
|
||||
"episode_cmd": ""
|
||||
}
|
@ -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,
|
||||
|
275
win_install.bat
275
win_install.bat
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user