mirror of
https://github.com/Arrowar/StreamingCommunity.git
synced 2025-06-05 02:55:25 +00:00
Bump v2.9.5
This commit is contained in:
parent
3e5b126c07
commit
64e382c32e
44
README.md
44
README.md
@ -45,6 +45,7 @@
|
||||
- 📥 [Download](#m3u8_download-settings)
|
||||
- 🔍 [Parser](#m3u8_parser-settings)
|
||||
- 📝 [Command](#command)
|
||||
- 🔍 [Global search](#global-search)
|
||||
- 💻 [Examples of terminal](#examples-of-terminal-usage)
|
||||
- 🔧 [Manual domain configuration](#update-domains)
|
||||
- 🐳 [Docker](#docker)
|
||||
@ -637,19 +638,41 @@ Note: If `use_api` is set to `false` and no `domains.json` file is found, the sc
|
||||
#### 💡 Adding a New Site to the Legacy API
|
||||
If you want to add a new site to the legacy API, just message me on the Discord server, and I'll add it!
|
||||
|
||||
# COMMAND
|
||||
# Global Search
|
||||
|
||||
- Download a specific season by entering its number.
|
||||
* **Example:** `1` will download *Season 1* only.
|
||||
You can now search across multiple streaming sites at once using the Global Search feature. This allows you to find content more efficiently without having to search each site individually.
|
||||
|
||||
- Use the wildcard `*` to download every available season.
|
||||
* **Example:** `*` will download all seasons in the series.
|
||||
## Using Global Search
|
||||
|
||||
- Specify a range of seasons using a hyphen `-`.
|
||||
* **Example:** `1-2` will download *Seasons 1 and 2*.
|
||||
The Global Search feature provides a unified interface to search across all supported sites:
|
||||
|
||||
- Enter a season number followed by `-*` to download from that season to the end.
|
||||
* **Example:** `3-*` will download from *Season 3* to the final season.
|
||||
## Search Options
|
||||
|
||||
When using Global Search, you have three ways to select which sites to search:
|
||||
|
||||
1. **Search all sites** - Searches across all available streaming sites
|
||||
2. **Search by category** - Group sites by their categories (movies, series, anime, etc.)
|
||||
3. **Select specific sites** - Choose individual sites to include in your search
|
||||
|
||||
## Navigation and Selection
|
||||
|
||||
After performing a search:
|
||||
|
||||
1. Results are displayed in a consolidated table showing:
|
||||
- Title
|
||||
- Media type (movie, TV series, etc.)
|
||||
- Source site
|
||||
|
||||
2. Select an item by number to view details or download
|
||||
|
||||
3. The system will automatically use the appropriate site's API to handle the download
|
||||
|
||||
## Command Line Arguments
|
||||
|
||||
The Global Search can be configured from the command line:
|
||||
|
||||
- `--global` - Perform a global search across multiple sites.
|
||||
- `-s`, `--search` - Specify the search terms.
|
||||
|
||||
# Examples of terminal usage
|
||||
|
||||
@ -662,6 +685,9 @@ python test_run.py --specific_list_audio ita,eng --specific_list_subtitles eng,s
|
||||
|
||||
# Keep console open after download
|
||||
python test_run.py --not_close true
|
||||
|
||||
# Use global search
|
||||
python test_run.py --global -s "cars"
|
||||
```
|
||||
|
||||
# Docker
|
||||
|
@ -10,10 +10,11 @@ from rich.prompt import Prompt
|
||||
|
||||
# Internal utilities
|
||||
from StreamingCommunity.Api.Template import get_select_title
|
||||
from StreamingCommunity.Api.Template.config_loader import site_constant
|
||||
from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
||||
|
||||
|
||||
# Logic class
|
||||
from StreamingCommunity.Api.Template.config_loader import site_constant
|
||||
from .site import title_search, media_search_manager, table_show_manager
|
||||
from .title import download_title
|
||||
|
||||
@ -29,30 +30,43 @@ console = Console()
|
||||
msg = Prompt()
|
||||
|
||||
|
||||
def search(string_to_search: str = None, get_onylDatabase: bool = False):
|
||||
|
||||
def process_search_result(select_title):
|
||||
"""
|
||||
Main function of the application for film and series.
|
||||
Handles the search result and initiates the download for either a film or series.
|
||||
"""
|
||||
download_title(select_title)
|
||||
|
||||
def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_item: dict = None):
|
||||
"""
|
||||
Main function of the application for search film, series and anime.
|
||||
|
||||
Parameters:
|
||||
string_to_search (str, optional): String to search for
|
||||
get_onylDatabase (bool, optional): If True, return only the database object
|
||||
direct_item (dict, optional): Direct item to process (bypass search)
|
||||
"""
|
||||
if direct_item:
|
||||
select_title = MediaItem(**direct_item)
|
||||
process_search_result(select_title)
|
||||
return
|
||||
|
||||
if string_to_search is None:
|
||||
string_to_search = msg.ask(f"\n[purple]Insert word to search in [green]{site_constant.SITE_NAME}").strip()
|
||||
|
||||
# Search on database
|
||||
# Perform the database search
|
||||
len_database = title_search(quote_plus(string_to_search))
|
||||
|
||||
# Return list of elements
|
||||
if get_onylDatabase:
|
||||
# If only the database is needed, return the manager
|
||||
if get_onlyDatabase:
|
||||
return media_search_manager
|
||||
|
||||
if len_database > 0:
|
||||
|
||||
# Select title from list
|
||||
select_title = get_select_title(table_show_manager, media_search_manager)
|
||||
|
||||
# Download title
|
||||
download_title(select_title)
|
||||
|
||||
else:
|
||||
console.print(f"\n[red]Nothing matching was found for[white]: [purple]{string_to_search}")
|
||||
|
||||
# Retry
|
||||
# If no results are found, ask again
|
||||
console.print(f"\n[red]Nothing matching was found for[white]: [purple]{string_to_search}")
|
||||
search()
|
@ -62,7 +62,8 @@ def title_search(word_to_search: str) -> int:
|
||||
'seader': tr.find_all("td")[-5].get_text(strip=True),
|
||||
'leacher': tr.find_all("td")[-4].get_text(strip=True),
|
||||
'date': tr.find_all("td")[-3].get_text(strip=True).replace("'", ""),
|
||||
'size': tr.find_all("td")[-2].get_text(strip=True)
|
||||
'size': tr.find_all("td")[-2].get_text(strip=True),
|
||||
'type': 'torrent'
|
||||
}
|
||||
media_search_manager.add_media(title_info)
|
||||
|
||||
|
@ -2,19 +2,22 @@
|
||||
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
from urllib.parse import quote_plus
|
||||
|
||||
|
||||
# External library
|
||||
from rich.console import Console
|
||||
from rich.prompt import Prompt
|
||||
|
||||
|
||||
# Internal utilities
|
||||
from StreamingCommunity.Api.Template import get_select_title
|
||||
from StreamingCommunity.Api.Template.config_loader import site_constant
|
||||
from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
||||
from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance
|
||||
|
||||
|
||||
# Logic class
|
||||
from StreamingCommunity.Api.Template.config_loader import site_constant
|
||||
from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance
|
||||
from .site import title_search, table_show_manager, media_search_manager
|
||||
from .film import download_film
|
||||
from .series import download_series
|
||||
@ -30,51 +33,76 @@ msg = Prompt()
|
||||
console = Console()
|
||||
|
||||
|
||||
def search(string_to_search: str = None, get_onylDatabase: bool = False):
|
||||
def get_user_input(string_to_search: str = None):
|
||||
"""
|
||||
Main function of the application for film and series.
|
||||
Asks the user to input a search term.
|
||||
Handles both Telegram bot input and direct input.
|
||||
"""
|
||||
|
||||
if site_constant.TELEGRAM_BOT:
|
||||
bot = get_bot_instance()
|
||||
|
||||
if string_to_search is None:
|
||||
|
||||
# Chiedi la scelta all'utente con il bot Telegram
|
||||
if string_to_search is None:
|
||||
if site_constant.TELEGRAM_BOT:
|
||||
bot = get_bot_instance()
|
||||
string_to_search = bot.ask(
|
||||
"key_search",
|
||||
f"Inserisci la parola da cercare\noppure back per tornare alla scelta: ",
|
||||
f"Enter the search term\nor type 'back' to return to the menu: ",
|
||||
None
|
||||
)
|
||||
|
||||
if string_to_search == 'back':
|
||||
# Riavvia lo script
|
||||
# Chiude il processo attuale e avvia una nuova istanza dello script
|
||||
|
||||
# Restart the script
|
||||
subprocess.Popen([sys.executable] + sys.argv)
|
||||
sys.exit()
|
||||
else:
|
||||
if string_to_search is None:
|
||||
string_to_search = msg.ask(f"\n[purple]Insert word to search in [green]{site_constant.SITE_NAME}").strip()
|
||||
else:
|
||||
string_to_search = msg.ask(f"\n[purple]Insert a word to search in [green]{site_constant.SITE_NAME}").strip()
|
||||
|
||||
return string_to_search
|
||||
|
||||
def process_search_result(select_title):
|
||||
"""
|
||||
Handles the search result and initiates the download for either a film or series.
|
||||
"""
|
||||
if select_title.type == 'tv':
|
||||
download_series(select_title)
|
||||
else:
|
||||
download_film(select_title)
|
||||
|
||||
def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_item: dict = None):
|
||||
"""
|
||||
Main function of the application for search film, series and anime.
|
||||
|
||||
Parameters:
|
||||
string_to_search (str, optional): String to search for
|
||||
get_onylDatabase (bool, optional): If True, return only the database object
|
||||
direct_item (dict, optional): Direct item to process (bypass search)
|
||||
"""
|
||||
if direct_item:
|
||||
select_title = MediaItem(**direct_item)
|
||||
process_search_result(select_title)
|
||||
return
|
||||
|
||||
# Get the user input for the search term
|
||||
string_to_search = get_user_input(string_to_search)
|
||||
|
||||
# Perform the database search
|
||||
len_database = title_search(quote_plus(string_to_search))
|
||||
|
||||
# Return list of elements
|
||||
if get_onylDatabase:
|
||||
# If only the database is needed, return the manager
|
||||
if get_onlyDatabase:
|
||||
return media_search_manager
|
||||
|
||||
|
||||
if site_constant.TELEGRAM_BOT:
|
||||
bot = get_bot_instance()
|
||||
|
||||
if len_database > 0:
|
||||
|
||||
# Select title from list
|
||||
select_title = get_select_title(table_show_manager, media_search_manager)
|
||||
|
||||
if select_title.type == 'tv':
|
||||
download_series(select_title)
|
||||
|
||||
else:
|
||||
download_film(select_title)
|
||||
|
||||
process_search_result(select_title)
|
||||
|
||||
else:
|
||||
console.print(f"\n[red]Nothing matching was found for[white]: [purple]{string_to_search}")
|
||||
|
||||
# Retry
|
||||
search()
|
||||
if site_constant.TELEGRAM_BOT:
|
||||
bot.send_message(f"No results found, please try again", None)
|
||||
|
||||
# If no results are found, ask again
|
||||
string_to_search = get_user_input()
|
||||
search()
|
@ -1,4 +1,4 @@
|
||||
# 3.12.23
|
||||
# 16.03.25
|
||||
|
||||
import os
|
||||
|
||||
@ -8,13 +8,14 @@ import httpx
|
||||
from bs4 import BeautifulSoup
|
||||
from rich.console import Console
|
||||
|
||||
from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance, TelegramSession
|
||||
|
||||
# Internal utilities
|
||||
from StreamingCommunity.Util.os import os_manager
|
||||
from StreamingCommunity.Util.message import start_message
|
||||
from StreamingCommunity.Util.headers import get_headers
|
||||
from StreamingCommunity.Util.config_json import config_manager
|
||||
from StreamingCommunity.Lib.Downloader import HLS_Downloader
|
||||
from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance, TelegramSession
|
||||
|
||||
|
||||
# Logic class
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 3.12.23
|
||||
# 16.03.25
|
||||
|
||||
import os
|
||||
from typing import Tuple
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 10.12.23
|
||||
# 16.03.25
|
||||
|
||||
|
||||
# External libraries
|
||||
@ -6,11 +6,12 @@ import httpx
|
||||
from bs4 import BeautifulSoup
|
||||
from rich.console import Console
|
||||
|
||||
from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance
|
||||
|
||||
# Internal utilities
|
||||
from StreamingCommunity.Util.config_json import config_manager
|
||||
from StreamingCommunity.Util.headers import get_userAgent
|
||||
from StreamingCommunity.Util.table import TVShowManager
|
||||
from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance
|
||||
|
||||
|
||||
# Logic class
|
||||
@ -61,10 +62,8 @@ def title_search(title_search: str) -> int:
|
||||
# Create soup istance
|
||||
soup = BeautifulSoup(response.text, "html.parser")
|
||||
|
||||
i = 0
|
||||
|
||||
# Collect data from soup
|
||||
for movie_div in soup.find_all("div", class_="movie"):
|
||||
for i, movie_div in enumerate(soup.find_all("div", class_="movie")):
|
||||
|
||||
title_tag = movie_div.find("h2", class_="movie-title")
|
||||
title = title_tag.find("a").get_text(strip=True)
|
||||
@ -86,8 +85,6 @@ def title_search(title_search: str) -> int:
|
||||
choice_text = f"{i} - {title} ({tipo})"
|
||||
choices.append(choice_text)
|
||||
|
||||
i += 1
|
||||
|
||||
if site_constant.TELEGRAM_BOT:
|
||||
if choices:
|
||||
bot.send_message(f"Lista dei risultati:", choices)
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 01.03.24
|
||||
# 16.03.25
|
||||
|
||||
# External libraries
|
||||
import httpx
|
||||
|
@ -11,11 +11,12 @@ from rich.prompt import Prompt
|
||||
|
||||
# Internal utilities
|
||||
from StreamingCommunity.Api.Template import get_select_title
|
||||
from StreamingCommunity.Api.Template.config_loader import site_constant
|
||||
from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
||||
from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance
|
||||
|
||||
|
||||
# Logic class
|
||||
from StreamingCommunity.Api.Template.config_loader import site_constant
|
||||
from .site import title_search, media_search_manager, table_show_manager
|
||||
from .film_serie import download_film, download_series
|
||||
|
||||
@ -31,53 +32,73 @@ msg = Prompt()
|
||||
console = Console()
|
||||
|
||||
|
||||
def search(string_to_search: str = None, get_onylDatabase: bool = False):
|
||||
|
||||
if site_constant.TELEGRAM_BOT:
|
||||
bot = get_bot_instance()
|
||||
|
||||
if string_to_search is None:
|
||||
|
||||
# Chiedi la scelta all'utente con il bot Telegram
|
||||
def get_user_input(string_to_search: str = None):
|
||||
"""
|
||||
Asks the user to input a search term.
|
||||
Handles both Telegram bot input and direct input.
|
||||
"""
|
||||
if string_to_search is None:
|
||||
if site_constant.TELEGRAM_BOT:
|
||||
bot = get_bot_instance()
|
||||
string_to_search = bot.ask(
|
||||
"key_search",
|
||||
f"Inserisci la parola da cercare\noppure back per tornare alla scelta: ",
|
||||
f"Enter the search term\nor type 'back' to return to the menu: ",
|
||||
None
|
||||
)
|
||||
|
||||
if string_to_search == 'back':
|
||||
# Riavvia lo script
|
||||
# Chiude il processo attuale e avvia una nuova istanza dello script
|
||||
|
||||
# Restart the script
|
||||
subprocess.Popen([sys.executable] + sys.argv)
|
||||
sys.exit()
|
||||
else:
|
||||
string_to_search = msg.ask(f"\n[purple]Insert a word to search in [green]{site_constant.SITE_NAME}").strip()
|
||||
|
||||
else:
|
||||
if string_to_search is None:
|
||||
string_to_search = msg.ask(f"\n[purple]Insert word to search in [green]{site_constant.SITE_NAME}").strip()
|
||||
return string_to_search
|
||||
|
||||
# Search on database
|
||||
def process_search_result(select_title):
|
||||
"""
|
||||
Handles the search result and initiates the download for either a film or series.
|
||||
"""
|
||||
download_series(select_title)
|
||||
|
||||
def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_item: dict = None):
|
||||
"""
|
||||
Main function of the application for search film, series and anime.
|
||||
|
||||
Parameters:
|
||||
string_to_search (str, optional): String to search for
|
||||
get_onlyDatabase (bool, optional): If True, return only the database object
|
||||
direct_item (dict, optional): Direct item to process (bypass search)
|
||||
"""
|
||||
if direct_item:
|
||||
select_title = MediaItem(**direct_item)
|
||||
process_search_result(select_title)
|
||||
return
|
||||
|
||||
# Get the user input for the search term
|
||||
string_to_search = get_user_input(string_to_search)
|
||||
|
||||
# Perform the database search
|
||||
len_database = title_search(string_to_search)
|
||||
|
||||
# Return list of elements
|
||||
if get_onylDatabase:
|
||||
##If only the database is needed, return the manager
|
||||
if get_onlyDatabase:
|
||||
return media_search_manager
|
||||
|
||||
if site_constant.TELEGRAM_BOT:
|
||||
bot = get_bot_instance()
|
||||
|
||||
if len_database > 0:
|
||||
|
||||
# Select title from list (type: TV \ Movie \ OVA)
|
||||
select_title = get_select_title(table_show_manager, media_search_manager)
|
||||
process_search_result(select_title)
|
||||
|
||||
if select_title.type == 'Movie' or select_title.type == 'OVA':
|
||||
download_film(select_title)
|
||||
|
||||
else:
|
||||
download_series(select_title)
|
||||
|
||||
else:
|
||||
if site_constant.TELEGRAM_BOT:
|
||||
bot.send_message(f"Nessun risultato trovato riprova", None)
|
||||
|
||||
console.print(f"\n[red]Nothing matching was found for[white]: [purple]{string_to_search}")
|
||||
|
||||
# Retry
|
||||
if site_constant.TELEGRAM_BOT:
|
||||
bot.send_message(f"No results found, please try again", None)
|
||||
|
||||
# If no results are found, ask again
|
||||
string_to_search = get_user_input()
|
||||
search()
|
@ -77,10 +77,8 @@ def get_real_title(record):
|
||||
"""
|
||||
if record['title_eng'] is not None:
|
||||
return record['title_eng']
|
||||
|
||||
elif record['title'] is not None:
|
||||
return record['title']
|
||||
|
||||
else:
|
||||
return record['title_it']
|
||||
|
||||
|
@ -10,10 +10,11 @@ from rich.prompt import Prompt
|
||||
|
||||
# Internal utilities
|
||||
from StreamingCommunity.Api.Template import get_select_title
|
||||
from StreamingCommunity.Api.Template.config_loader import site_constant
|
||||
from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
||||
|
||||
|
||||
# Logic class
|
||||
from StreamingCommunity.Api.Template.config_loader import site_constant
|
||||
from .site import title_search, media_search_manager, table_show_manager
|
||||
from .film import download_film
|
||||
|
||||
@ -29,10 +30,26 @@ msg = Prompt()
|
||||
console = Console()
|
||||
|
||||
|
||||
def search(string_to_search: str = None, get_onylDatabase: bool = False):
|
||||
def process_search_result(select_title):
|
||||
"""
|
||||
Main function of the application for film and series.
|
||||
Handles the search result and initiates the download for either a film or series.
|
||||
"""
|
||||
# !!! ADD TYPE DONT WORK FOR SERIE
|
||||
download_film(select_title)
|
||||
|
||||
def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_item: dict = None):
|
||||
"""
|
||||
Main function of the application for search film, series and anime.
|
||||
|
||||
Parameters:
|
||||
string_to_search (str, optional): String to search for
|
||||
get_onylDatabase (bool, optional): If True, return only the database object
|
||||
direct_item (dict, optional): Direct item to process (bypass search)
|
||||
"""
|
||||
if direct_item:
|
||||
select_title = MediaItem(**direct_item)
|
||||
process_search_result(select_title)
|
||||
return
|
||||
|
||||
if string_to_search is None:
|
||||
string_to_search = msg.ask(f"\n[purple]Insert word to search in [green]{site_constant.SITE_NAME}").strip()
|
||||
@ -40,21 +57,16 @@ def search(string_to_search: str = None, get_onylDatabase: bool = False):
|
||||
# Search on database
|
||||
len_database = title_search(quote_plus(string_to_search))
|
||||
|
||||
# Return list of elements
|
||||
if get_onylDatabase:
|
||||
## If only the database is needed, return the manager
|
||||
if get_onlyDatabase:
|
||||
return media_search_manager
|
||||
|
||||
if len_database > 0:
|
||||
|
||||
# Select title from list
|
||||
select_title = get_select_title(table_show_manager, media_search_manager)
|
||||
|
||||
# !!! ADD TYPE DONT WORK FOR SERIE
|
||||
download_film(select_title)
|
||||
|
||||
|
||||
process_search_result(select_title)
|
||||
|
||||
else:
|
||||
console.print(f"\n[red]Nothing matching was found for[white]: [purple]{string_to_search}")
|
||||
|
||||
# Retry
|
||||
# If no results are found, ask again
|
||||
console.print(f"\n[red]Nothing matching was found for[white]: [purple]{string_to_search}")
|
||||
search()
|
@ -62,7 +62,8 @@ def title_search(word_to_search: str) -> int:
|
||||
|
||||
title_info = {
|
||||
'name': title,
|
||||
'url': url
|
||||
'url': url,
|
||||
'type': 'film'
|
||||
}
|
||||
|
||||
media_search_manager.add_media(title_info)
|
||||
|
@ -12,6 +12,7 @@ from rich.prompt import Prompt
|
||||
# Internal utilities
|
||||
from StreamingCommunity.Api.Template import get_select_title
|
||||
from StreamingCommunity.Api.Template.config_loader import site_constant
|
||||
from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
||||
|
||||
|
||||
# Logic class
|
||||
@ -30,10 +31,28 @@ msg = Prompt()
|
||||
console = Console()
|
||||
|
||||
|
||||
def search(string_to_search: str = None, get_onylDatabase: bool = False):
|
||||
def process_search_result(select_title):
|
||||
"""
|
||||
Main function of the application for film and series.
|
||||
Handles the search result and initiates the download for either a film or series.
|
||||
"""
|
||||
if "Serie TV" in str(select_title.type):
|
||||
download_thread(select_title)
|
||||
else:
|
||||
logging.error(f"Not supported: {select_title.type}")
|
||||
|
||||
def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_item: dict = None):
|
||||
"""
|
||||
Main function of the application for search film, series and anime.
|
||||
|
||||
Parameters:
|
||||
string_to_search (str, optional): String to search for
|
||||
get_onylDatabase (bool, optional): If True, return only the database object
|
||||
direct_item (dict, optional): Direct item to process (bypass search)
|
||||
"""
|
||||
if direct_item:
|
||||
select_title = MediaItem(**direct_item)
|
||||
process_search_result(select_title)
|
||||
return
|
||||
|
||||
if string_to_search is None:
|
||||
string_to_search = msg.ask(f"\n[purple]Insert word to search in [green]{site_constant.SITE_NAME}").strip()
|
||||
@ -41,24 +60,16 @@ def search(string_to_search: str = None, get_onylDatabase: bool = False):
|
||||
# Search on database
|
||||
len_database = title_search(quote_plus(string_to_search))
|
||||
|
||||
# Return list of elements
|
||||
if get_onylDatabase:
|
||||
# If only the database is needed, return the manager
|
||||
if get_onlyDatabase:
|
||||
return media_search_manager
|
||||
|
||||
if len_database > 0:
|
||||
|
||||
# Select title from list
|
||||
select_title = get_select_title(table_show_manager, media_search_manager)
|
||||
|
||||
# Download only film
|
||||
if "Serie TV" in str(select_title.type):
|
||||
download_thread(select_title)
|
||||
|
||||
else:
|
||||
logging.error(f"Not supported: {select_title.type}")
|
||||
process_search_result(select_title)
|
||||
|
||||
else:
|
||||
|
||||
# If no results are found, ask again
|
||||
console.print(f"\n[red]Nothing matching was found for[white]: [purple]{string_to_search}")
|
||||
|
||||
# Retry
|
||||
search()
|
@ -11,6 +11,7 @@ from rich.prompt import Prompt
|
||||
# Internal utilities
|
||||
from StreamingCommunity.Api.Template import get_select_title
|
||||
from StreamingCommunity.Api.Template.config_loader import site_constant
|
||||
from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
||||
|
||||
|
||||
# Logic class
|
||||
@ -29,10 +30,25 @@ msg = Prompt()
|
||||
console = Console()
|
||||
|
||||
|
||||
def search(string_to_search: str = None, get_onylDatabase: bool = False):
|
||||
def process_search_result(select_title):
|
||||
"""
|
||||
Main function of the application for film and series.
|
||||
Handles the search result and initiates the download for either a film or series.
|
||||
"""
|
||||
download_series(select_title)
|
||||
|
||||
def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_item: dict = None):
|
||||
"""
|
||||
Main function of the application for search film, series and anime.
|
||||
|
||||
Parameters:
|
||||
string_to_search (str, optional): String to search for
|
||||
get_onylDatabase (bool, optional): If True, return only the database object
|
||||
direct_item (dict, optional): Direct item to process (bypass search)
|
||||
"""
|
||||
if direct_item:
|
||||
select_title = MediaItem(**direct_item)
|
||||
process_search_result(select_title)
|
||||
return
|
||||
|
||||
if string_to_search is None:
|
||||
string_to_search = msg.ask(f"\n[purple]Insert word to search in [green]{site_constant.SITE_NAME}").strip()
|
||||
@ -40,20 +56,16 @@ def search(string_to_search: str = None, get_onylDatabase: bool = False):
|
||||
# Search on database
|
||||
len_database = title_search(quote_plus(string_to_search))
|
||||
|
||||
# Return list of elements
|
||||
if get_onylDatabase:
|
||||
# If only the database is needed, return the manager
|
||||
if get_onlyDatabase:
|
||||
return media_search_manager
|
||||
|
||||
if len_database > 0:
|
||||
|
||||
# Select title from list
|
||||
select_title = get_select_title(table_show_manager, media_search_manager)
|
||||
|
||||
# Download only film
|
||||
download_series(select_title)
|
||||
process_search_result(select_title)
|
||||
|
||||
else:
|
||||
console.print(f"\n[red]Nothing matching was found for[white]: [purple]{string_to_search}")
|
||||
|
||||
# Retry
|
||||
# If no results are found, ask again
|
||||
console.print(f"\n[red]Nothing matching was found for[white]: [purple]{string_to_search}")
|
||||
search()
|
@ -63,7 +63,8 @@ def title_search(word_to_search: str) -> int:
|
||||
|
||||
serie_info = {
|
||||
'name': title,
|
||||
'url': link
|
||||
'url': link,
|
||||
'type': 'tv'
|
||||
}
|
||||
|
||||
media_search_manager.add_media(serie_info)
|
||||
|
@ -5,12 +5,16 @@ from urllib.parse import quote_plus
|
||||
|
||||
# External library
|
||||
from rich.console import Console
|
||||
from rich.prompt import Prompt, Confirm
|
||||
from rich.prompt import Prompt
|
||||
|
||||
|
||||
# Internal utilities
|
||||
from StreamingCommunity.Api.Template.config_loader import site_constant
|
||||
from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
||||
from StreamingCommunity.Lib.TMBD import tmdb, Json_film
|
||||
|
||||
|
||||
# Logic class
|
||||
from StreamingCommunity.Api.Template.config_loader import site_constant
|
||||
from StreamingCommunity.Lib.TMBD import tmdb, Json_film
|
||||
from .film import download_film
|
||||
|
||||
|
||||
@ -25,16 +29,32 @@ msg = Prompt()
|
||||
console = Console()
|
||||
|
||||
|
||||
def search(string_to_search: str = None, get_onylDatabase: bool = False):
|
||||
def process_search_result(select_title):
|
||||
"""
|
||||
Main function of the application for film and series.
|
||||
Handles the search result and initiates the download for either a film or series.
|
||||
"""
|
||||
download_film(select_title)
|
||||
|
||||
|
||||
def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_item: dict = None):
|
||||
"""
|
||||
Main function of the application for search film, series and anime.
|
||||
|
||||
Parameters:
|
||||
string_to_search (str, optional): String to search for
|
||||
get_onylDatabase (bool, optional): If True, return only the database object
|
||||
direct_item (dict, optional): Direct item to process (bypass search)
|
||||
"""
|
||||
if direct_item:
|
||||
select_title = MediaItem(**direct_item)
|
||||
process_search_result(select_title)
|
||||
return
|
||||
|
||||
if string_to_search is None:
|
||||
string_to_search = msg.ask(f"\n[purple]Insert word to search in [green]{site_constant.SITE_NAME}").strip()
|
||||
|
||||
# Not available for the moment
|
||||
if get_onylDatabase:
|
||||
if get_onlyDatabase:
|
||||
return 0
|
||||
|
||||
# Search on database
|
||||
@ -47,7 +67,7 @@ def search(string_to_search: str = None, get_onylDatabase: bool = False):
|
||||
download_film(movie_details)
|
||||
|
||||
else:
|
||||
console.print(f"\n[red]Nothing matching was found for[white]: [purple]{string_to_search}")
|
||||
|
||||
# Retry
|
||||
# If no results are found, ask again
|
||||
console.print(f"\n[red]Nothing matching was found for[white]: [purple]{string_to_search}")
|
||||
search()
|
@ -12,11 +12,12 @@ from rich.prompt import Prompt
|
||||
|
||||
# Internal utilities
|
||||
from StreamingCommunity.Api.Template import get_select_title
|
||||
from StreamingCommunity.Api.Template.config_loader import site_constant
|
||||
from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
||||
from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance
|
||||
|
||||
|
||||
# Logic class
|
||||
from StreamingCommunity.Api.Template.config_loader import site_constant
|
||||
from .site import title_search, table_show_manager, media_search_manager
|
||||
from .film import download_film
|
||||
from .series import download_series
|
||||
@ -33,54 +34,76 @@ msg = Prompt()
|
||||
console = Console()
|
||||
|
||||
|
||||
def search(string_to_search: str = None, get_onylDatabase: bool = False):
|
||||
def get_user_input(string_to_search: str = None):
|
||||
"""
|
||||
Main function of the application for film and series.
|
||||
Asks the user to input a search term.
|
||||
Handles both Telegram bot input and direct input.
|
||||
"""
|
||||
if site_constant.TELEGRAM_BOT:
|
||||
bot = get_bot_instance()
|
||||
|
||||
if string_to_search is None:
|
||||
|
||||
# Chiedi la scelta all'utente con il bot Telegram
|
||||
if string_to_search is None:
|
||||
if site_constant.TELEGRAM_BOT:
|
||||
bot = get_bot_instance()
|
||||
string_to_search = bot.ask(
|
||||
"key_search",
|
||||
f"Inserisci la parola da cercare\noppure back per tornare alla scelta: ",
|
||||
f"Enter the search term\nor type 'back' to return to the menu: ",
|
||||
None
|
||||
)
|
||||
|
||||
if string_to_search == 'back':
|
||||
# Riavvia lo script
|
||||
# Chiude il processo attuale e avvia una nuova istanza dello script
|
||||
|
||||
# Restart the script
|
||||
subprocess.Popen([sys.executable] + sys.argv)
|
||||
sys.exit()
|
||||
|
||||
else:
|
||||
if string_to_search is None:
|
||||
string_to_search = msg.ask(f"\n[purple]Insert word to search in [green]{site_constant.SITE_NAME}").strip()
|
||||
else:
|
||||
string_to_search = msg.ask(f"\n[purple]Insert a word to search in [green]{site_constant.SITE_NAME}").strip()
|
||||
|
||||
return string_to_search
|
||||
|
||||
def process_search_result(select_title):
|
||||
"""
|
||||
Handles the search result and initiates the download for either a film or series.
|
||||
"""
|
||||
if select_title.type == 'tv':
|
||||
download_series(select_title)
|
||||
else:
|
||||
download_film(select_title)
|
||||
|
||||
def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_item: dict = None):
|
||||
"""
|
||||
Main function of the application for search film, series and anime.
|
||||
|
||||
Parameters:
|
||||
string_to_search (str, optional): String to search for
|
||||
get_onylDatabase (bool, optional): If True, return only the database object
|
||||
direct_item (dict, optional): Direct item to process (bypass search)
|
||||
"""
|
||||
if direct_item:
|
||||
select_title = MediaItem(**direct_item)
|
||||
process_search_result(select_title)
|
||||
return
|
||||
|
||||
# Get the user input for the search term
|
||||
string_to_search = get_user_input(string_to_search)
|
||||
|
||||
# Perform the database search
|
||||
len_database = title_search(quote_plus(string_to_search))
|
||||
|
||||
# Return list of elements
|
||||
if get_onylDatabase:
|
||||
# If only the database is needed, return the manager
|
||||
if get_onlyDatabase:
|
||||
return media_search_manager
|
||||
|
||||
if site_constant.TELEGRAM_BOT:
|
||||
bot = get_bot_instance()
|
||||
|
||||
if len_database > 0:
|
||||
|
||||
# Select title from list
|
||||
select_title = get_select_title(table_show_manager, media_search_manager)
|
||||
|
||||
if select_title.type == 'tv':
|
||||
download_series(select_title)
|
||||
|
||||
else:
|
||||
download_film(select_title)
|
||||
process_search_result(select_title)
|
||||
|
||||
else:
|
||||
console.print(f"\n[red]Nothing matching was found for[white]: [purple]{string_to_search}")
|
||||
|
||||
if site_constant.TELEGRAM_BOT:
|
||||
bot.send_message(f"Nessun risultato trovato riprova", None)
|
||||
bot.send_message(f"No results found, please try again", None)
|
||||
|
||||
# Retry
|
||||
# If no results are found, ask again
|
||||
string_to_search = get_user_input()
|
||||
search()
|
@ -1,5 +1,5 @@
|
||||
__title__ = 'StreamingCommunity'
|
||||
__version__ = '2.9.4'
|
||||
__version__ = '2.9.5'
|
||||
__author__ = 'Arrowar'
|
||||
__description__ = 'A command-line program to download film'
|
||||
__copyright__ = 'Copyright 2024'
|
||||
|
315
StreamingCommunity/global_search.py
Normal file
315
StreamingCommunity/global_search.py
Normal file
@ -0,0 +1,315 @@
|
||||
# 17.03.25
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import glob
|
||||
import logging
|
||||
import importlib
|
||||
|
||||
|
||||
# External library
|
||||
from rich.console import Console
|
||||
from rich.prompt import Prompt
|
||||
from rich.table import Table
|
||||
from rich.progress import Progress
|
||||
|
||||
|
||||
# Internal utilities
|
||||
from StreamingCommunity.Util.message import start_message
|
||||
|
||||
|
||||
# Variable
|
||||
console = Console()
|
||||
msg = Prompt()
|
||||
|
||||
|
||||
# !!! DA METTERE IN COMUNE CON QUELLA DI RUN
|
||||
def load_search_functions():
|
||||
modules = []
|
||||
loaded_functions = {}
|
||||
excluded_sites = set()
|
||||
|
||||
# Find api home directory
|
||||
if getattr(sys, 'frozen', False): # Modalità PyInstaller
|
||||
base_path = os.path.join(sys._MEIPASS, "StreamingCommunity")
|
||||
else:
|
||||
base_path = os.path.dirname(__file__)
|
||||
|
||||
api_dir = os.path.join(base_path, 'Api', 'Site')
|
||||
init_files = glob.glob(os.path.join(api_dir, '*', '__init__.py'))
|
||||
|
||||
# Retrieve modules and their indices
|
||||
for init_file in init_files:
|
||||
|
||||
# Get folder name as module name
|
||||
module_name = os.path.basename(os.path.dirname(init_file))
|
||||
|
||||
# Se il modulo è nella lista da escludere, saltalo
|
||||
if module_name in excluded_sites:
|
||||
continue
|
||||
|
||||
logging.info(f"Load module name: {module_name}")
|
||||
|
||||
try:
|
||||
# Dynamically import the module
|
||||
mod = importlib.import_module(f'StreamingCommunity.Api.Site.{module_name}')
|
||||
|
||||
# Get 'indice' from the module
|
||||
indice = getattr(mod, 'indice', 0)
|
||||
is_deprecate = bool(getattr(mod, '_deprecate', True))
|
||||
use_for = getattr(mod, '_useFor', 'other')
|
||||
|
||||
if not is_deprecate:
|
||||
modules.append((module_name, indice, use_for))
|
||||
|
||||
except Exception as e:
|
||||
console.print(f"[red]Failed to import module {module_name}: {str(e)}")
|
||||
|
||||
# Sort modules by 'indice'
|
||||
modules.sort(key=lambda x: x[1])
|
||||
|
||||
# Load search functions in the sorted order
|
||||
for module_name, _, use_for in modules:
|
||||
|
||||
# Construct a unique alias for the module
|
||||
module_alias = f'{module_name}_search'
|
||||
|
||||
try:
|
||||
|
||||
# Dynamically import the module
|
||||
mod = importlib.import_module(f'StreamingCommunity.Api.Site.{module_name}')
|
||||
|
||||
# Get the search function from the module (assuming the function is named 'search' and defined in __init__.py)
|
||||
search_function = getattr(mod, 'search')
|
||||
|
||||
# Add the function to the loaded functions dictionary
|
||||
loaded_functions[module_alias] = (search_function, use_for)
|
||||
|
||||
except Exception as e:
|
||||
console.print(f"[red]Failed to load search function from module {module_name}: {str(e)}")
|
||||
|
||||
return loaded_functions
|
||||
|
||||
def global_search(search_terms: str = None, selected_sites: list = None):
|
||||
"""
|
||||
Perform a search across multiple sites based on selection.
|
||||
|
||||
Parameters:
|
||||
search_terms (str, optional): The terms to search for. If None, will prompt the user.
|
||||
selected_sites (list, optional): List of site aliases to search. If None, will search all sites.
|
||||
|
||||
Returns:
|
||||
dict: Consolidated search results from all searched sites.
|
||||
"""
|
||||
search_functions = load_search_functions()
|
||||
all_results = {}
|
||||
|
||||
if search_terms is None:
|
||||
search_terms = msg.ask("\n[purple]Enter search terms for global search: ").strip()
|
||||
|
||||
# Organize sites by category for better display
|
||||
sites_by_category = {}
|
||||
for alias, (func, category) in search_functions.items():
|
||||
if category not in sites_by_category:
|
||||
sites_by_category[category] = []
|
||||
sites_by_category[category].append((alias, func))
|
||||
|
||||
# If no sites are specifically selected, prompt the user
|
||||
if selected_sites is None:
|
||||
console.print("\n[bold green]Select sites to search:[/bold green]")
|
||||
console.print("[bold cyan]1.[/bold cyan] Search all sites")
|
||||
console.print("[bold cyan]2.[/bold cyan] Search by category")
|
||||
console.print("[bold cyan]3.[/bold cyan] Select specific sites")
|
||||
|
||||
choice = msg.ask("[green]Enter your choice (1-3)", choices=["1", "2", "3"], default="1")
|
||||
|
||||
if choice == "1":
|
||||
# Search all sites
|
||||
selected_sites = list(search_functions.keys())
|
||||
|
||||
elif choice == "2":
|
||||
# Search by category
|
||||
console.print("\n[bold green]Select categories to search:[/bold green]")
|
||||
for i, category in enumerate(sites_by_category.keys(), 1):
|
||||
console.print(f"[bold cyan]{i}.[/bold cyan] {category.capitalize()}")
|
||||
|
||||
category_choices = msg.ask("[green]Enter category numbers separated by commas", default="1")
|
||||
selected_categories = [list(sites_by_category.keys())[int(c.strip())-1] for c in category_choices.split(",")]
|
||||
|
||||
selected_sites = []
|
||||
for category in selected_categories:
|
||||
for alias, _ in sites_by_category.get(category, []):
|
||||
selected_sites.append(alias)
|
||||
|
||||
else:
|
||||
# Select specific sites
|
||||
console.print("\n[bold green]Select specific sites to search:[/bold green]")
|
||||
|
||||
for i, (alias, _) in enumerate(search_functions.items(), 1):
|
||||
site_name = alias.split("_")[0].capitalize()
|
||||
console.print(f"[bold cyan]{i}.[/bold cyan] {site_name}")
|
||||
|
||||
site_choices = msg.ask("[green]Enter site numbers separated by commas", default="1")
|
||||
selected_indices = [int(c.strip())-1 for c in site_choices.split(",")]
|
||||
selected_sites = [list(search_functions.keys())[i] for i in selected_indices if i < len(search_functions)]
|
||||
|
||||
# Display progress information
|
||||
console.print(f"\n[bold green]Searching for:[/bold green] [yellow]{search_terms}[/yellow]")
|
||||
console.print(f"[bold green]Searching across:[/bold green] {len(selected_sites)} sites")
|
||||
|
||||
with Progress() as progress:
|
||||
search_task = progress.add_task("[cyan]Searching...", total=len(selected_sites))
|
||||
|
||||
# Search each selected site
|
||||
for alias in selected_sites:
|
||||
site_name = alias.split("_")[0].capitalize()
|
||||
progress.update(search_task, description=f"[cyan]Searching {site_name}...")
|
||||
|
||||
func, _ = search_functions[alias]
|
||||
try:
|
||||
# Call the search function with get_onlyDatabase=True to get database object
|
||||
database = func(search_terms, get_onlyDatabase=True)
|
||||
|
||||
# Check if database has media_list attribute and it's not empty
|
||||
if database and hasattr(database, 'media_list') and len(database.media_list) > 0:
|
||||
# Store media_list items with additional source information
|
||||
all_results[alias] = []
|
||||
for element in database.media_list:
|
||||
# Convert element to dictionary if it's an object
|
||||
if hasattr(element, '__dict__'):
|
||||
item_dict = element.__dict__.copy()
|
||||
else:
|
||||
item_dict = {} # Fallback for non-object items
|
||||
|
||||
# Add source information
|
||||
item_dict['source'] = site_name
|
||||
item_dict['source_alias'] = alias
|
||||
all_results[alias].append(item_dict)
|
||||
|
||||
console.print(f"[green]Found {len(database.media_list)} results from {site_name}")
|
||||
|
||||
except Exception as e:
|
||||
console.print(f"[bold red]Error searching {site_name}:[/bold red] {str(e)}")
|
||||
|
||||
progress.update(search_task, advance=1)
|
||||
|
||||
# Display the consolidated results
|
||||
if all_results:
|
||||
all_media_items = []
|
||||
for alias, results in all_results.items():
|
||||
for item in results:
|
||||
all_media_items.append(item)
|
||||
|
||||
# Display consolidated results
|
||||
display_consolidated_results(all_media_items, search_terms)
|
||||
|
||||
# Allow user to select an item
|
||||
selected_item = select_from_consolidated_results(all_media_items)
|
||||
if selected_item:
|
||||
# Process the selected item - download or further actions
|
||||
process_selected_item(selected_item, search_functions)
|
||||
|
||||
else:
|
||||
console.print(f"\n[bold red]No results found for:[/bold red] [yellow]{search_terms}[/yellow]")
|
||||
|
||||
# Optionally offer to search again or return to main menu
|
||||
if msg.ask("[green]Search again? (y/n)", choices=["y", "n"], default="y") == "y":
|
||||
global_search()
|
||||
|
||||
return all_results
|
||||
|
||||
def display_consolidated_results(all_media_items, search_terms):
|
||||
"""
|
||||
Display consolidated search results from multiple sites.
|
||||
|
||||
Parameters:
|
||||
all_media_items (list): List of media items from all searched sites.
|
||||
search_terms (str): The search terms used.
|
||||
"""
|
||||
time.sleep(1)
|
||||
start_message()
|
||||
|
||||
console.print(f"\n[bold green]Search results for:[/bold green] [yellow]{search_terms}[/yellow] \n")
|
||||
|
||||
table = Table(show_header=True, header_style="bold cyan")
|
||||
table.add_column("#", style="dim", width=4)
|
||||
table.add_column("Title", min_width=20)
|
||||
table.add_column("Type", width=15)
|
||||
table.add_column("Source", width=25)
|
||||
|
||||
for i, item in enumerate(all_media_items, 1):
|
||||
|
||||
# Extract values from item dict, with fallbacks if keys don't exist
|
||||
title = item.get('title', item.get('name', 'Unknown'))
|
||||
media_type = item.get('type', item.get('media_type', 'Unknown'))
|
||||
source = item.get('source', 'Unknown')
|
||||
|
||||
table.add_row(
|
||||
str(i),
|
||||
str(title),
|
||||
str(media_type),
|
||||
str(source),
|
||||
)
|
||||
|
||||
console.print(table)
|
||||
|
||||
def select_from_consolidated_results(all_media_items):
|
||||
"""
|
||||
Allow user to select an item from consolidated results.
|
||||
|
||||
Parameters:
|
||||
all_media_items (list): List of media items from all searched sites.
|
||||
|
||||
Returns:
|
||||
dict: The selected media item or None if no selection was made.
|
||||
"""
|
||||
if not all_media_items:
|
||||
return None
|
||||
|
||||
max_index = len(all_media_items)
|
||||
choice = msg.ask(
|
||||
f"[green]Select item # (1-{max_index}) or 0 to cancel",
|
||||
choices=[str(i) for i in range(max_index + 1)],
|
||||
default="1",
|
||||
show_choices=False
|
||||
)
|
||||
|
||||
if choice == "0":
|
||||
return None
|
||||
|
||||
return all_media_items[int(choice) - 1]
|
||||
|
||||
def process_selected_item(selected_item, search_functions):
|
||||
"""
|
||||
Process the selected item - download the media using the appropriate site API.
|
||||
|
||||
Parameters:
|
||||
selected_item (dict): The selected media item.
|
||||
search_functions (dict): Dictionary of search functions by alias.
|
||||
"""
|
||||
source_alias = selected_item.get('source_alias')
|
||||
if not source_alias or source_alias not in search_functions:
|
||||
console.print("[bold red]Error: Cannot process this item - source information missing.[/bold red]")
|
||||
return
|
||||
|
||||
# Get the appropriate search function for this source
|
||||
func, _ = search_functions[source_alias]
|
||||
|
||||
console.print(f"\n[bold green]Processing selection from:[/bold green] {selected_item.get('source')}")
|
||||
|
||||
# Extract necessary information to pass to the site's search function
|
||||
item_id = selected_item.get('id', selected_item.get('media_id'))
|
||||
item_type = selected_item.get('type', selected_item.get('media_type', 'unknown'))
|
||||
item_title = selected_item.get('title', selected_item.get('name', 'Unknown'))
|
||||
|
||||
if item_id:
|
||||
console.print(f"[bold green]Selected item:[/bold green] {item_title} (ID: {item_id}, Type: {item_type})")
|
||||
|
||||
# Call the site's search function with direct_item parameter to process download
|
||||
try:
|
||||
func(direct_item=selected_item)
|
||||
except Exception as e:
|
||||
console.print(f"[bold red]Error processing download:[/bold red] {str(e)}")
|
||||
else:
|
||||
console.print("[bold red]Error: Item ID not found.[/bold red]")
|
@ -18,6 +18,7 @@ from rich.prompt import Prompt
|
||||
|
||||
|
||||
# Internal utilities
|
||||
from .global_search import global_search
|
||||
from StreamingCommunity.Util.message import start_message
|
||||
from StreamingCommunity.Util.config_json import config_manager
|
||||
from StreamingCommunity.Util.os import os_summary
|
||||
@ -54,6 +55,7 @@ def run_function(func: Callable[..., None], close_console: bool = False, search_
|
||||
func(search_terms)
|
||||
|
||||
|
||||
# !!! DA METTERE IN COMUNE CON QUELLA DI GLOBAL
|
||||
def load_search_functions():
|
||||
modules = []
|
||||
loaded_functions = {}
|
||||
@ -237,6 +239,11 @@ def main(script_id = 0):
|
||||
'--specific_list_subtitles', type=str, help='Comma-separated list of specific subtitle languages to download (e.g., eng,spa).'
|
||||
)
|
||||
|
||||
# Add global search option
|
||||
parser.add_argument(
|
||||
'--global', action='store_true', help='Perform a global search across multiple sites.'
|
||||
)
|
||||
|
||||
# Add arguments for search functions
|
||||
color_map = {
|
||||
"anime": "red",
|
||||
@ -253,6 +260,7 @@ def main(script_id = 0):
|
||||
parser.add_argument(f'-{short_option}', f'--{long_option}', action='store_true', help=f'Search for {alias.split("_")[0]} on streaming platforms.')
|
||||
|
||||
parser.add_argument('-s', '--search', default=None, help='Search terms')
|
||||
|
||||
# Parse command-line arguments
|
||||
args = parser.parse_args()
|
||||
|
||||
@ -280,6 +288,11 @@ def main(script_id = 0):
|
||||
|
||||
config_manager.write_config()
|
||||
|
||||
# Check if global search is requested
|
||||
if getattr(args, 'global'):
|
||||
global_search(search_terms)
|
||||
return
|
||||
|
||||
# Map command-line arguments to functions
|
||||
arg_to_function = {alias: func for alias, (func, _) in search_functions.items()}
|
||||
|
||||
@ -295,13 +308,18 @@ def main(script_id = 0):
|
||||
# Create dynamic prompt message and choices
|
||||
choice_labels = {str(i): (alias.split("_")[0].capitalize(), use_for) for i, (alias, (_, use_for)) in enumerate(search_functions.items())}
|
||||
|
||||
# Add global search option to the menu
|
||||
#global_search_key = str(len(choice_labels))
|
||||
#choice_labels[global_search_key] = ("Global Search", "all")
|
||||
#input_to_function[global_search_key] = global_search
|
||||
|
||||
# Display the category legend in a single line
|
||||
legend_text = " | ".join([f"[{color}]{category.capitalize()}[/{color}]" for category, color in color_map.items()])
|
||||
console.print(f"\n[bold green]Category Legend:[/bold green] {legend_text}")
|
||||
|
||||
# Construct the prompt message with color-coded site names
|
||||
prompt_message = "[green]Insert category [white](" + ", ".join(
|
||||
[f"{key}: [{color_map[label[1]]}]{label[0]}[/{color_map[label[1]]}]" for key, label in choice_labels.items()]
|
||||
[f"{key}: [{color_map.get(label[1], 'white')}]{label[0]}[/{color_map.get(label[1], 'white')}]" for key, label in choice_labels.items()]
|
||||
) + "[white])"
|
||||
|
||||
if TELEGRAM_BOT:
|
||||
@ -330,10 +348,16 @@ def main(script_id = 0):
|
||||
|
||||
# Run the corresponding function based on user input
|
||||
if category in input_to_function:
|
||||
run_function(input_to_function[category], search_terms = args.search)
|
||||
"""if category == global_search_key:
|
||||
# Run global search
|
||||
run_function(input_to_function[category], search_terms=search_terms)
|
||||
|
||||
else:"""
|
||||
|
||||
# Run normal site-specific search
|
||||
run_function(input_to_function[category], search_terms=search_terms)
|
||||
|
||||
else:
|
||||
|
||||
if TELEGRAM_BOT:
|
||||
bot.send_message(f"Categoria non valida", None)
|
||||
|
||||
|
@ -1,116 +0,0 @@
|
||||
# 12.11.24
|
||||
|
||||
# Fix import
|
||||
import os
|
||||
import sys
|
||||
src_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
|
||||
sys.path.append(src_path)
|
||||
|
||||
|
||||
# Other
|
||||
import glob
|
||||
import logging
|
||||
import importlib
|
||||
from rich.console import Console
|
||||
|
||||
|
||||
# Other import
|
||||
from StreamingCommunity.Api.Template.Class.SearchType import MediaManager
|
||||
|
||||
|
||||
# Variable
|
||||
console = Console()
|
||||
|
||||
|
||||
def load_search_functions():
|
||||
modules = []
|
||||
loaded_functions = {}
|
||||
|
||||
# Traverse the Api directory
|
||||
api_dir = os.path.join(os.path.dirname(__file__), '..', 'StreamingCommunity', 'Api', 'Site')
|
||||
init_files = glob.glob(os.path.join(api_dir, '*', '__init__.py'))
|
||||
|
||||
logging.info(f"Base folder path: {api_dir}")
|
||||
logging.info(f"Api module path: {init_files}")
|
||||
|
||||
# Retrieve modules and their indices
|
||||
for init_file in init_files:
|
||||
|
||||
# Get folder name as module name
|
||||
module_name = os.path.basename(os.path.dirname(init_file))
|
||||
logging.info(f"Load module name: {module_name}")
|
||||
|
||||
try:
|
||||
# Dynamically import the module
|
||||
mod = importlib.import_module(f'StreamingCommunity.Api.Site.{module_name}')
|
||||
|
||||
# Get 'indice' from the module
|
||||
indice = getattr(mod, 'indice', 0)
|
||||
is_deprecate = bool(getattr(mod, '_deprecate', True))
|
||||
use_for = getattr(mod, '_useFor', 'other')
|
||||
|
||||
if not is_deprecate:
|
||||
modules.append((module_name, indice, use_for))
|
||||
|
||||
except Exception as e:
|
||||
console.print(f"[red]Failed to import module {module_name}: {str(e)}")
|
||||
|
||||
# Sort modules by 'indice'
|
||||
modules.sort(key=lambda x: x[1])
|
||||
|
||||
# Load search functions in the sorted order
|
||||
for module_name, _, use_for in modules:
|
||||
|
||||
# Construct a unique alias for the module
|
||||
module_alias = f'{module_name}_search'
|
||||
logging.info(f"Module alias: {module_alias}")
|
||||
|
||||
try:
|
||||
# Dynamically import the module
|
||||
mod = importlib.import_module(f'StreamingCommunity.Api.Site.{module_name}')
|
||||
|
||||
# Get the search function from the module (assuming the function is named 'search' and defined in __init__.py)
|
||||
search_function = getattr(mod, 'search')
|
||||
|
||||
# Add the function to the loaded functions dictionary
|
||||
loaded_functions[module_alias] = (search_function, use_for)
|
||||
|
||||
except Exception as e:
|
||||
console.print(f"[red]Failed to load search function from module {module_name}: {str(e)}")
|
||||
|
||||
return loaded_functions
|
||||
|
||||
|
||||
def search_all_sites(loaded_functions, search_string, max_sites=10):
|
||||
total_len_database = 0
|
||||
site_count = 0
|
||||
|
||||
for module_alias, (search_function, use_for) in loaded_functions.items():
|
||||
if max_sites is not None and site_count >= max_sites:
|
||||
break
|
||||
|
||||
console.print(f"\n[blue]Searching in module: {module_alias} [white](Use for: {use_for})")
|
||||
|
||||
try:
|
||||
database: MediaManager = search_function(search_string, get_onylDatabase=True)
|
||||
len_database = len(database.media_list)
|
||||
|
||||
for element in database.media_list:
|
||||
print(element.__dict__)
|
||||
|
||||
console.print(f"[green]Database length for {module_alias}: {len_database}")
|
||||
total_len_database += len_database
|
||||
site_count += 1
|
||||
|
||||
except Exception as e:
|
||||
console.print(f"[red]Error while executing search function for {module_alias}: {str(e)}")
|
||||
|
||||
return total_len_database
|
||||
|
||||
|
||||
# Main
|
||||
search_string = "cars"
|
||||
loaded_functions = load_search_functions()
|
||||
|
||||
total_len = search_all_sites(loaded_functions, search_string)
|
||||
console.print(f"\n[cyan]Total number of results from all sites: {total_len}")
|
Loading…
x
Reference in New Issue
Block a user