Fix table and trending show.

This commit is contained in:
Lovi-0 2024-09-01 16:23:31 +02:00
parent 0f31abd946
commit 3f983f334f
6 changed files with 26 additions and 225 deletions

View File

@ -1,3 +0,0 @@
# 19.04.24
from .page import search

View File

@ -1,127 +0,0 @@
# 19.04.24
import time
import logging
from urllib.parse import quote_plus, urlparse, parse_qs
from typing import Generator, Optional
# External libraries
import httpx
from bs4 import BeautifulSoup
def filter_result(link: str) -> Optional[str]:
"""
Filters search result links to remove unwanted ones.
Parameters:
- link (str): The URL of the search result.
Returns:
Optional[str]: The filtered URL if valid, None otherwise.
"""
try:
logging.info(f"Filter url: {link}")
if link.startswith('/url?'):
# Extract the actual URL from Google's redirect link
o = urlparse(link, 'http')
link = parse_qs(o.query)['q'][0]
o = urlparse(link, 'http')
# Filter out Google links
if o.netloc and 'google' not in o.netloc:
return link
except Exception:
pass
def search(query: str, num: int = 10, stop: Optional[int] = None, pause: float = 2.0) -> Generator[str, None, None]:
"""
Performs a Google search and yields the URLs of search results.
Parameters:
- query (str): The search query.
- num (int): Number of results to fetch per request. Default is 10.
- stop (int, optional): Total number of results to retrieve. Default is None.
- pause (float): Pause duration between requests. Default is 2.0.
Yields:
str: The URL of a search result.
Example:
>>> for url in search("Python tutorials", num=5, stop=10):
... print(url)
...
https://www.python.org/about/gettingstarted/
"""
# Set to store unique URLs
hashes = set()
# Counter for the number of fetched URLs
count = 0
# Encode the query for URL
query = quote_plus(query)
while not stop or count < stop:
last_count = count
# Construct the Google search URL
url = f"https://www.google.com/search?client=opera&q={query}&sourceid=opera&oe=UTF-8"
# Pause before making the request
time.sleep(pause)
# Fetch the HTML content of the search page
html = httpx.get(url).text
soup = BeautifulSoup(html, 'html.parser')
try:
# Find all anchor tags containing search result links
anchors = soup.find(id='search').findAll('a')
except AttributeError:
# Handle cases where search results are not found in the usual div
gbar = soup.find(id='gbar')
if gbar:
gbar.clear()
anchors = soup.findAll('a')
# Iterate over each anchor tag
for a in anchors:
try:
link = a['href']
except KeyError:
continue
# Filter out unwanted links
link = filter_result(link)
if not link:
continue
# Check for duplicate URLs
h = hash(link)
if h in hashes:
continue
hashes.add(h)
# Yield the valid URL
yield link
# Increment the counter
count += 1
# Check if the desired number of URLs is reached
if stop and count >= stop:
return
# Break the loop if no new URLs are found
if last_count == count:
break

View File

@ -18,7 +18,7 @@ api_key = "a800ed6c93274fb857ea61bd9e7256c5"
class TheMovieDB: class TheMovieDB:
def __init__(self, api_key, tv_show_manager): def __init__(self, api_key):
""" """
Initialize the class with the API key and TV show manager. Initialize the class with the API key and TV show manager.
@ -29,7 +29,6 @@ class TheMovieDB:
self.api_key = api_key self.api_key = api_key
self.base_url = "https://api.themoviedb.org/3" self.base_url = "https://api.themoviedb.org/3"
self.console = Console() self.console = Console()
self.tv_show_manager = tv_show_manager
self.genres = self._fetch_genres() self.genres = self._fetch_genres()
def _make_request(self, endpoint, params=None): def _make_request(self, endpoint, params=None):
@ -72,26 +71,27 @@ class TheMovieDB:
- columns (list): A list of tuples, where each tuple contains the column name and the key to fetch the data from the dictionary. - 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 # Define column styles with colors
tv_show_manager = TVShowManager()
column_info = { column_info = {
col[0]: {'color': col[2] if len(col) > 2 else 'white'} col[0]: {'color': col[2] if len(col) > 2 else 'white'}
for col in columns for col in columns
} }
self.tv_show_manager.add_column(column_info) tv_show_manager.add_column(column_info)
# Add each item to the TV show manager, including rank # Add each item to the TV show manager, including rank
for index, item in enumerate(data): for index, item in enumerate(data):
# Convert genre IDs to genre names # Convert genre IDs to genre names
genre_names = [self.genres.get(genre_id, 'Unknown') for genre_id in item.get('genre_ids', [])] genre_names = [self.genres.get(genre_id, 'Unknown') for genre_id in item.get('genre_ids', [])]
tv_show = { tv_show = {
col[0]: str(item.get(col[1], 'N/A')) if col[1] != 'genre_ids' else ', '.join(genre_names) 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' for col in columns
} }
# Add rank manually
tv_show['Rank'] = str(index + 1) tv_show_manager.add_tv_show(tv_show)
self.tv_show_manager.add_tv_show(tv_show)
# Display the processed TV show data # 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]) tv_show_manager.display_data(tv_show_manager.tv_shows[tv_show_manager.slice_start:tv_show_manager.slice_end])
def _display_with_title(self, title: str, data, columns): def _display_with_title(self, title: str, data, columns):
""" """
@ -111,13 +111,12 @@ class TheMovieDB:
""" """
data = self._make_request("trending/tv/week").get("results", []) data = self._make_request("trending/tv/week").get("results", [])
columns = [ columns = [
("Rank", None, 'yellow'),
("Title", "name", 'cyan'), ("Title", "name", 'cyan'),
("First Air Date", "first_air_date", 'green'), ("First Air Date", "first_air_date", 'green'),
("Popularity", "popularity", 'magenta'), ("Popularity", "popularity", 'magenta'),
("Genres", "genre_ids", 'blue'), ("Genres", "genre_ids", 'blue'),
("Origin Country", "origin_country", 'red'), ("Origin Country", "origin_country", 'red'),
("Vote Average", "vote_average", 'white') ("Vote Average", "vote_average", 'yellow')
] ]
self._display_with_title("Trending TV Shows of the Week", data, columns) self._display_with_title("Trending TV Shows of the Week", data, columns)
@ -127,87 +126,13 @@ class TheMovieDB:
""" """
data = self._make_request("trending/movie/week").get("results", []) data = self._make_request("trending/movie/week").get("results", [])
columns = [ columns = [
("Rank", None, 'yellow'),
("Title", "title", 'cyan'), ("Title", "title", 'cyan'),
("Release Date", "release_date", 'green'), ("Release Date", "release_date", 'green'),
("Popularity", "popularity", 'magenta'), ("Popularity", "popularity", 'magenta'),
("Genres", "genre_ids", 'blue'), ("Genres", "genre_ids", 'blue'),
("Vote Average", "vote_average", 'white') ("Vote Average", "vote_average", 'yellow')
] ]
self._display_with_title("Trending Films of the Week", data, columns) 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)
# Output # Output
tmdb = TheMovieDB(api_key, tv_show_manager) tmdb = TheMovieDB(api_key)

View File

@ -102,7 +102,7 @@ class TVShowManager:
# Handling user input for loading more items or quitting # Handling user input for loading more items or quitting
if self.slice_end < total_items: if self.slice_end < total_items:
self.console.print(f"\n\n[yellow][INFO] [green]Press [red]Enter [green]to restart, or [red]'q' [green]to quit.") self.console.print(f"\n\n[yellow][INFO] [green]Press [red]Enter [green]for next page, or [red]'q' [green]to quit.")
if not force_int_input: if not force_int_input:
key = Prompt.ask("\n[cyan]Insert media [red]index [yellow]or [red](*) [cyan]to download all media [yellow]or [red][1-2] [cyan]or [red][3-*] [cyan]for a range of media") key = Prompt.ask("\n[cyan]Insert media [red]index [yellow]or [red](*) [cyan]to download all media [yellow]or [red][1-2] [cyan]or [red][3-*] [cyan]for a range of media")
@ -118,8 +118,8 @@ class TVShowManager:
break break
elif key == "": elif key == "":
self.slice_start += self.slice_end self.slice_start += self.step
self.slice_end += self.slice_end self.slice_end += self.step
if self.slice_end > total_items: if self.slice_end > total_items:
self.slice_end = total_items self.slice_end = total_items
@ -127,7 +127,8 @@ class TVShowManager:
break break
else: else:
self.console.print(f"\n\n[yellow][INFO] [red]You've reached the end. [green]Press [red]Enter [green]to restart, or [red]'q' [green]to quit.") # Last slice, ensure all remaining items are shown
self.console.print(f"\n\n[yellow][INFO] [red]You've reached the end. [green]Press [red]Enter [green]for next page, or [red]'q' [green]to quit.")
if not force_int_input: if not force_int_input:
key = Prompt.ask("\n[cyan]Insert media [red]index [yellow]or [red](*) [cyan]to download all media [yellow]or [red][1-2] [cyan]or [red][3-*] [cyan]for a range of media") key = Prompt.ask("\n[cyan]Insert media [red]index [yellow]or [red](*) [cyan]to download all media [yellow]or [red][1-2] [cyan]or [red][3-*] [cyan]for a range of media")
@ -149,6 +150,6 @@ class TVShowManager:
break break
return last_command return last_command
def clear(self): def clear(self):
self.tv_shows = [] self.tv_shows = []

View File

@ -13,7 +13,8 @@
"user": "admin", "user": "admin",
"pass": "adminadmin" "pass": "adminadmin"
}, },
"not_close": false "not_close": false,
"show_trending": true
}, },
"REQUESTS": { "REQUESTS": {
"timeout": 10, "timeout": 10,

10
run.py
View File

@ -23,6 +23,7 @@ from Src.Util.logger import Logger
# Config # Config
CLOSE_CONSOLE = config_manager.get_bool('DEFAULT', 'not_close') CLOSE_CONSOLE = config_manager.get_bool('DEFAULT', 'not_close')
SHOW_TRENDING = config_manager.get_bool('DEFAULT', 'show_trending')
def run_function(func: Callable[..., None], close_console: bool = False) -> None: def run_function(func: Callable[..., None], close_console: bool = False) -> None:
@ -129,9 +130,12 @@ def initialize():
console.log("[red]Error with loading github.") console.log("[red]Error with loading github.")
# Show trending film and series # Show trending film and series
tmdb.display_trending_films() if SHOW_TRENDING:
tmdb.display_trending_tv_shows() tmdb.display_trending_films()
print()
tmdb.display_trending_tv_shows()
print()
def main(): def main():