diff --git a/README.md b/README.md index 7b17aac..024bbba 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ This repository provide a simple script designed to facilitate the downloading of films and series from a popular streaming community platform. The script allows users to download individual films, entire series, or specific episodes, providing a seamless experience for content consumers. -## Join us +## Join us 🌟 You can chat, help improve this repo, or just hang around for some fun in the **Git_StreamingCommunity** Discord [Server](https://discord.com/invite/8vV68UGRc7) # Table of Contents @@ -22,7 +22,7 @@ You can chat, help improve this repo, or just hang around for some fun in the ** * [TO DO](#to-do) -## Requirement +## Requirement 📋 Make sure you have the following prerequisites installed on your system: @@ -30,7 +30,7 @@ Make sure you have the following prerequisites installed on your system: * [ffmpeg](https://www.gyan.dev/ffmpeg/builds/) * [openssl](https://www.openssl.org) or [pycryptodome](https://pypi.org/project/pycryptodome/) -## Installation +## Installation ⚙️ Install the required Python libraries using the following command: @@ -38,7 +38,7 @@ Install the required Python libraries using the following command: pip install -r requirements.txt ``` -## Usage +## Usage 📚 Run the script with the following command: @@ -72,7 +72,7 @@ python3 update_version.py ``` -## Configuration +## Configuration ⚙️ You can change some behaviors by tweaking the configuration file. @@ -198,7 +198,7 @@ You can choose different vars: > NOTE: You don't need to add .mp4 at the end -## Docker +## Docker 🐳 You can run the script in a docker container, to build the image just run @@ -231,14 +231,14 @@ make LOCAL_DIR=/path/to/download run-container The `run-container` command mounts also the `config.json` file, so any change to the configuration file is reflected immediately without having to rebuild the image. -## Tutorial +## 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) -## To do +## To do 📝 - GUI - Website api - Add other site diff --git a/Src/Lib/TMBD/tmbd.py b/Src/Lib/TMBD/tmbd.py new file mode 100644 index 0000000..ae75efb --- /dev/null +++ b/Src/Lib/TMBD/tmbd.py @@ -0,0 +1,214 @@ +# 24.08.24 + +from typing import Dict + + +# External libraries +import httpx +from rich.console import Console + + +# Internal utilities +from Src.Util.table import TVShowManager + + +class TheMovieDB: + def __init__(self, api_key, tv_show_manager): + """ + Initialize the class with the API key and TV show manager. + + Parameters: + - api_key (str): The API key for authenticating requests to TheMovieDB. + - tv_show_manager (TVShowManager): An instance of the TVShowManager for handling TV show items. + """ + self.api_key = api_key + self.base_url = "https://api.themoviedb.org/3" + self.console = Console() + self.tv_show_manager = tv_show_manager + self.genres = self._fetch_genres() + + def _make_request(self, endpoint, params=None): + """ + Make a request to the given API endpoint with optional parameters. + + Parameters: + - endpoint (str): The API endpoint to hit. + - params (dict): Additional parameters for the request. + + Returns: + dict: JSON response as a dictionary. + """ + if params is None: + params = {} + + params['api_key'] = self.api_key + url = f"{self.base_url}/{endpoint}" + response = httpx.get(url, params=params) + response.raise_for_status() + + return response.json() + + def _fetch_genres(self) -> Dict[int, str]: + """ + Fetch and return the genre names from TheMovieDB. + + Returns: + Dict[int, str]: A dictionary mapping genre IDs to genre names. + """ + genres = self._make_request("genre/tv/list") + return {genre['id']: genre['name'] for genre in genres.get('genres', [])} + + def _process_and_add_tv_shows(self, data, columns): + """ + Process TV show data and add it to the TV show manager. + + Parameters: + - data (list): List of dictionaries containing the data to process. + - columns (list): A list of tuples, where each tuple contains the column name and the key to fetch the data from the dictionary. + """ + # Define column styles with colors + column_info = { + col[0]: {'color': col[2] if len(col) > 2 else 'white'} + for col in columns + } + self.tv_show_manager.add_column(column_info) + + # Add each item to the TV show manager, including rank + for index, item in enumerate(data): + # Convert genre IDs to genre names + genre_names = [self.genres.get(genre_id, 'Unknown') for genre_id in item.get('genre_ids', [])] + tv_show = { + col[0]: str(item.get(col[1], 'N/A')) if col[1] != 'genre_ids' else ', '.join(genre_names) + for col in columns if col[0] != 'Rank' + } + # Add rank manually + tv_show['Rank'] = str(index + 1) + self.tv_show_manager.add_tv_show(tv_show) + + # Display the processed TV show data + self.tv_show_manager.display_data(self.tv_show_manager.tv_shows[self.tv_show_manager.slice_start:self.tv_show_manager.slice_end]) + + def _display_with_title(self, title: str, data, columns): + """ + Display data with a title. + + Parameters: + - title (str): The title to display. + - data (list): List of dictionaries containing the data to process. + - columns (list): A list of tuples, where each tuple contains the column name and the key to fetch the data from the dictionary. + """ + self.console.print(f"\n{title}", style="bold underline") + self._process_and_add_tv_shows(data, columns) + + def display_trending_tv_shows(self): + """ + Fetch and display the trending TV shows of the week. + """ + data = self._make_request("trending/tv/week").get("results", []) + columns = [ + ("Rank", None, 'yellow'), + ("Title", "name", 'cyan'), + ("First Air Date", "first_air_date", 'green'), + ("Popularity", "popularity", 'magenta'), + ("Genres", "genre_ids", 'blue'), + ("Origin Country", "origin_country", 'red'), + ("Vote Average", "vote_average", 'white') + ] + self._display_with_title("Trending TV Shows of the Week", data, columns) + + def display_trending_films(self): + """ + Fetch and display the trending films of the week. + """ + data = self._make_request("trending/movie/week").get("results", []) + columns = [ + ("Rank", None, 'yellow'), + ("Title", "title", 'cyan'), + ("Release Date", "release_date", 'green'), + ("Popularity", "popularity", 'magenta'), + ("Genres", "genre_ids", 'blue'), + ("Vote Average", "vote_average", 'white') + ] + self._display_with_title("Trending Films of the Week", data, columns) + + def display_recent_films(self): + """ + Fetch and display the films released recently. + """ + data = self._make_request("movie/now_playing").get("results", []) + columns = [ + ("Rank", None, 'yellow'), + ("Title", "title", 'cyan'), + ("Release Date", "release_date", 'green'), + ("Popularity", "popularity", 'magenta'), + ("Genres", "genre_ids", 'blue'), + ("Vote Average", "vote_average", 'white') + ] + self._display_with_title("Recently Released Films", data, columns) + + def display_recent_tv_shows(self): + """ + Fetch and display the TV shows airing recently. + """ + data = self._make_request("tv/on_the_air").get("results", []) + columns = [ + ("Rank", None, 'yellow'), + ("Title", "name", 'cyan'), + ("First Air Date", "first_air_date", 'green'), + ("Popularity", "popularity", 'magenta'), + ("Genres", "genre_ids", 'blue'), + ("Origin Country", "origin_country", 'red'), + ("Vote Average", "vote_average", 'white') + ] + self._display_with_title("Recently Aired TV Shows", data, columns) + + def search_by_genre(self, genre_id): + """ + Fetch and display TV shows based on genre. + + Parameters: + - genre_id (int): The genre ID to filter the results. + """ + endpoint = "discover/tv" + params = {"with_genres": genre_id, "sort_by": "popularity.desc"} + data = self._make_request(endpoint, params).get("results", []) + columns = [ + ("Rank", None, 'yellow'), + ("Title", "name", 'cyan'), + ("First Air Date", "first_air_date", 'green'), + ("Popularity", "popularity", 'magenta'), + ("Genres", "genre_ids", 'blue'), + ("Origin Country", "origin_country", 'red'), + ("Vote Average", "vote_average", 'white') + ] + self._display_with_title(f"TV Shows by Genre {genre_id}", data, columns) + + def search_by_title(self, title): + """ + Search and display TV shows by title. + + Parameters: + - title (str): The title to search for. + """ + endpoint = "search/tv" + params = {"query": title} + data = self._make_request(endpoint, params).get("results", []) + columns = [ + ("Rank", None, 'yellow'), + ("Title", "name", 'cyan'), + ("First Air Date", "first_air_date", 'green'), + ("Popularity", "popularity", 'magenta'), + ("Genres", "genre_ids", 'blue'), + ("Origin Country", "origin_country", 'red'), + ("Vote Average", "vote_average", 'white') + ] + self._display_with_title(f"Search Results for: {title}", data, columns) + + + +# Create an instance of TVShowManager +tv_show_manager = TVShowManager() + +# Replace with your actual API key +api_key = "a800ed6c93274fb857ea61bd9e7256c5" +tmdb = TheMovieDB(api_key, tv_show_manager) \ No newline at end of file diff --git a/Src/Util/os.py b/Src/Util/os.py index b50284d..2483d20 100644 --- a/Src/Util/os.py +++ b/Src/Util/os.py @@ -6,12 +6,10 @@ import os import sys import ssl import time -import json import errno import shutil import hashlib import logging -import zipfile import platform import importlib import subprocess @@ -19,17 +17,12 @@ import contextlib import urllib.request import importlib.metadata -from typing import List - - # External library import httpx import unicodedata - # Internal utilities from .console import console -from .headers import get_headers @@ -284,14 +277,14 @@ def compute_sha1_hash(input_string: str) -> str: def check_internet(): while True: try: - # Attempt to open a connection to a website to check for internet connection - urllib.request.urlopen("https://www.google.com", timeout=3) + httpx.get("https://www.google.com") console.log("[bold green]Internet is available![/bold green]") break except urllib.error.URLError: console.log("[bold red]Internet is not available. Waiting...[/bold red]") time.sleep(5) + print() def get_executable_version(command): diff --git a/requirements.txt b/requirements.txt index ddf62d3..eeb9b0e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,6 +7,7 @@ tqdm m3u8 psutil unidecode +jsbeautifier seleniumbase fake-useragent qbittorrent-api diff --git a/run.py b/run.py index 020dcb8..f88d1ee 100644 --- a/run.py +++ b/run.py @@ -17,6 +17,7 @@ from Src.Util.console import console, msg from Src.Util._jsonConfig import config_manager from Src.Upload.update import update as git_update from Src.Util.os import get_system_summary +from Src.Lib.TMBD.tmbd import tmdb from Src.Util.logger import Logger @@ -125,12 +126,15 @@ def initialize(): # Attempting GitHub update try: - #git_update() + git_update() print() except: console.log("[red]Error with loading github.") - + # Show trending film and series + tmdb.display_trending_films() + tmdb.display_trending_tv_shows() + def main():