diff --git a/README.md b/README.md index bb349dd..8f3e390 100644 --- a/README.md +++ b/README.md @@ -797,13 +797,27 @@ Contributions are welcome! Steps: 4. Push to branch (`git push origin feature/AmazingFeature`) 5. Open Pull Request - # Disclaimer This software is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose, and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages, or other liability, whether in an action of contract, tort, or otherwise, arising from, out of, or in connection with the software or the use or other dealings in the software. +## Useful Project + +### 🎯 [Unit3Dup](https://github.com/31December99/Unit3Dup) +Bot in Python per la generazione e l'upload automatico di torrent su tracker basati su Unit3D. + + +### 🇮🇹 [MammaMia](https://github.com/UrloMythus/MammaMia) +Addon per Stremio che consente lo streaming HTTPS di film, serie, anime e TV in diretta in lingua italiana. + +### 🧩 [streamingcommunity-unofficialapi](https://github.com/Blu-Tiger/streamingcommunity-unofficialapi) +API non ufficiale per accedere ai contenuti del sito italiano StreamingCommunity. + +### 🎥 [stream-buddy](https://github.com/Bbalduzz/stream-buddy) +Tool per guardare o scaricare film dalla piattaforma StreamingCommunity. + ## Contributors Contributors - + \ No newline at end of file diff --git a/StreamingCommunity/Api/Player/hdplayer.py b/StreamingCommunity/Api/Player/hdplayer.py new file mode 100644 index 0000000..c3db7e7 --- /dev/null +++ b/StreamingCommunity/Api/Player/hdplayer.py @@ -0,0 +1,101 @@ +# 29.04.25 + +import re +import logging + + +# External libraries +import httpx +from bs4 import BeautifulSoup + + +# Internal utilities +from StreamingCommunity.Util.config_json import config_manager +from StreamingCommunity.Util.headers import get_userAgent + + +# Variable +MAX_TIMEOUT = config_manager.get_int("REQUESTS", "timeout") + + +class VideoSource: + def __init__(self, url: str): + """ + Sets up the video source with the provided URL. + + Parameters: + - url (str): The URL of the video. + """ + self.url = url + self.iframe_url = None + self.m3u8_url = None + self.headers = { + 'accept': '*/*', + 'accept-language': 'en-US,en;q=0.9', + 'user-agent': get_userAgent(), + 'referer': url + } + + def extract_iframe_sources(self, response) -> str: + """Extract iframe source from the page.""" + try: + soup = BeautifulSoup(response.content, 'html.parser') + iframes = soup.select("iframe[data-lazy-src]") + + if not iframes: + iframes = soup.select("iframe[src]") + + if iframes: + iframe_url = iframes[0].get('data-lazy-src') or iframes[0].get('src') + self.iframe_url = iframe_url + logging.info(f"Iframe URL found: {iframe_url}") + return iframe_url + + logging.error("No iframes found in the page") + return None + + except Exception as e: + logging.error(f"Error extracting iframe: {e}") + raise + + def get_m3u8_url(self) -> str: + """ + Extract m3u8 URL from hdPlayer page. + """ + try: + # First request to get iframe + response = httpx.get(self.url, headers=self.headers, timeout=MAX_TIMEOUT) + response.raise_for_status() + + iframe_url = self.extract_iframe_sources(response) + if not iframe_url: + raise ValueError("No iframe URL found") + + # Update headers for iframe request + self.headers['referer'] = iframe_url + + # Request to iframe page + logging.info(f"Making request to hdPlayer: {iframe_url}") + response = httpx.get(iframe_url, headers=self.headers, timeout=MAX_TIMEOUT) + response.raise_for_status() + + # Find m3u8 in the script + soup = BeautifulSoup(response.text, 'html.parser') + scripts = soup.find_all("script") + + for script in scripts: + if not script.string: + continue + + match = re.search(r'sources:\s*\[\{\s*file:\s*"([^"]+)"', script.string) + if match: + self.m3u8_url = match.group(1) + logging.info(f"Found m3u8 URL: {self.m3u8_url}") + return self.m3u8_url + + logging.error("No m3u8 URL found in scripts") + return None + + except Exception as e: + logging.error(f"Error getting m3u8 URL: {e}") + raise \ No newline at end of file diff --git a/StreamingCommunity/Api/Site/1337xx/site.py b/StreamingCommunity/Api/Site/1337xx/site.py index b1891aa..59dff4f 100644 --- a/StreamingCommunity/Api/Site/1337xx/site.py +++ b/StreamingCommunity/Api/Site/1337xx/site.py @@ -52,7 +52,7 @@ def title_search(query: str) -> int: response.raise_for_status() except Exception as e: - console.print(f"Site: {site_constant.SITE_NAME}, request search error: {e}") + console.print(f"[red]Site: {site_constant.SITE_NAME}, request search error: {e}") return 0 # Create soup and find table diff --git a/StreamingCommunity/Api/Site/altadefinizione/site.py b/StreamingCommunity/Api/Site/altadefinizione/site.py index 4404078..9356f90 100644 --- a/StreamingCommunity/Api/Site/altadefinizione/site.py +++ b/StreamingCommunity/Api/Site/altadefinizione/site.py @@ -55,7 +55,7 @@ def title_search(query: str) -> int: response.raise_for_status() except Exception as e: - console.print(f"Site: {site_constant.SITE_NAME}, request search error: {e}") + console.print(f"[red]Site: {site_constant.SITE_NAME}, request search error: {e}") if site_constant.TELEGRAM_BOT: bot.send_message(f"ERRORE\n\nErrore nella richiesta di ricerca:\n\n{e}", None) return 0 diff --git a/StreamingCommunity/Api/Site/animeunity/site.py b/StreamingCommunity/Api/Site/animeunity/site.py index 448248e..0994f80 100644 --- a/StreamingCommunity/Api/Site/animeunity/site.py +++ b/StreamingCommunity/Api/Site/animeunity/site.py @@ -119,7 +119,8 @@ def title_search(query: str) -> int: process_results(response1.json()['records'], seen_titles, media_search_manager, choices) except Exception as e: - console.print(f"Site: {site_constant.SITE_NAME}, livesearch error: {e}") + console.print(f"[red]Site: {site_constant.SITE_NAME}, request search error: {e}") + return 0 # Second API call - archivio try: diff --git a/StreamingCommunity/Api/Site/animeworld/site.py b/StreamingCommunity/Api/Site/animeworld/site.py index a24bc14..e154c24 100644 --- a/StreamingCommunity/Api/Site/animeworld/site.py +++ b/StreamingCommunity/Api/Site/animeworld/site.py @@ -78,7 +78,7 @@ def title_search(query: str) -> int: ) except Exception as e: - console.print(f"Site: {site_constant.SITE_NAME}, request search error: {e}") + console.print(f"[red]Site: {site_constant.SITE_NAME}, request search error: {e}") return 0 # Create soup istance diff --git a/StreamingCommunity/Api/Site/ddlstreamitaly/site.py b/StreamingCommunity/Api/Site/ddlstreamitaly/site.py index 7c9230c..98afb66 100644 --- a/StreamingCommunity/Api/Site/ddlstreamitaly/site.py +++ b/StreamingCommunity/Api/Site/ddlstreamitaly/site.py @@ -53,7 +53,7 @@ def title_search(query: str) -> int: response.raise_for_status() except Exception as e: - console.print(f"Site: {site_constant.SITE_NAME}, request search error: {e}") + console.print(f"[red]Site: {site_constant.SITE_NAME}, request search error: {e}") return 0 # Create soup and find table diff --git a/StreamingCommunity/Api/Site/guardaserie/site.py b/StreamingCommunity/Api/Site/guardaserie/site.py index ca111c8..3fabd61 100644 --- a/StreamingCommunity/Api/Site/guardaserie/site.py +++ b/StreamingCommunity/Api/Site/guardaserie/site.py @@ -54,7 +54,7 @@ def title_search(query: str) -> int: response.raise_for_status() except Exception as e: - console.print(f"Site: {site_constant.SITE_NAME}, request search error: {e}") + console.print(f"[red]Site: {site_constant.SITE_NAME}, request search error: {e}") return 0 # Create soup and find table diff --git a/StreamingCommunity/Api/Site/raiplay/site.py b/StreamingCommunity/Api/Site/raiplay/site.py index 2ac07a0..c4a4b1e 100644 --- a/StreamingCommunity/Api/Site/raiplay/site.py +++ b/StreamingCommunity/Api/Site/raiplay/site.py @@ -26,7 +26,7 @@ console = Console() media_search_manager = MediaManager() table_show_manager = TVShowManager() max_timeout = config_manager.get_int("REQUESTS", "timeout") -MAX_THREADS = 4 +MAX_THREADS = 12 def determine_media_type(title): @@ -134,7 +134,7 @@ def title_search(query: str) -> int: response.raise_for_status() except Exception as e: - console.print(f"Site: {site_constant.SITE_NAME}, request search error: {e}") + console.print(f"[red]Site: {site_constant.SITE_NAME}, request search error: {e}") return 0 # Limit to only 15 results for performance diff --git a/StreamingCommunity/Api/Site/streamingcommunity/site.py b/StreamingCommunity/Api/Site/streamingcommunity/site.py index d781d6f..5c7fc89 100644 --- a/StreamingCommunity/Api/Site/streamingcommunity/site.py +++ b/StreamingCommunity/Api/Site/streamingcommunity/site.py @@ -55,7 +55,7 @@ def title_search(query: str) -> int: response.raise_for_status() except Exception as e: - console.print(f"Site: {site_constant.SITE_NAME}, request search error: {e}") + console.print(f"[red]Site: {site_constant.SITE_NAME}, request search error: {e}") if site_constant.TELEGRAM_BOT: bot.send_message(f"ERRORE\n\nErrore nella richiesta di ricerca:\n\n{e}", None) return 0 diff --git a/StreamingCommunity/Api/Site/streamingwatch/film.py b/StreamingCommunity/Api/Site/streamingwatch/film.py index 847c822..b7362e1 100644 --- a/StreamingCommunity/Api/Site/streamingwatch/film.py +++ b/StreamingCommunity/Api/Site/streamingwatch/film.py @@ -41,8 +41,8 @@ def download_film(select_title: MediaItem) -> str: console.print(f"[bold yellow]Download:[/bold yellow] [red]{site_constant.SITE_NAME}[/red] → [cyan]{select_title.name}[/cyan] \n") # Get master playlists - video_source = VideoSource() - master_playlist = video_source.get_m3u8_url(select_title.url) + video_source = VideoSource(select_title.url) + master_playlist = video_source.get_m3u8_url() # Define the filename and path for the downloaded film title_name = os_manager.get_sanitize_file(select_title.name) + ".mp4" diff --git a/StreamingCommunity/Api/Site/streamingwatch/series.py b/StreamingCommunity/Api/Site/streamingwatch/series.py index f6a1358..818d1d3 100644 --- a/StreamingCommunity/Api/Site/streamingwatch/series.py +++ b/StreamingCommunity/Api/Site/streamingwatch/series.py @@ -60,8 +60,8 @@ def download_video(index_season_selected: int, index_episode_selected: int, scra mp4_path = os.path.join(site_constant.SERIES_FOLDER, scrape_serie.series_name, f"S{index_season_selected}") # Retrieve scws and if available master playlist - video_source = VideoSource() - master_playlist = video_source.get_m3u8_url(obj_episode.url) + video_source = VideoSource(obj_episode.url) + master_playlist = video_source.get_m3u8_url() # Download the episode r_proc = HLS_Downloader(