StreamingCommunity 2.9.3__py3-none-any.whl → 2.9.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of StreamingCommunity might be problematic. Click here for more details.
- StreamingCommunity/Api/Player/Helper/Vixcloud/util.py +40 -38
- StreamingCommunity/Api/Player/maxstream.py +3 -11
- StreamingCommunity/Api/Site/1337xx/__init__.py +26 -12
- StreamingCommunity/Api/Site/1337xx/site.py +3 -10
- StreamingCommunity/Api/Site/altadefinizione/__init__.py +108 -0
- StreamingCommunity/Api/Site/altadefinizione/film.py +128 -0
- StreamingCommunity/Api/Site/altadefinizione/series.py +209 -0
- StreamingCommunity/Api/Site/altadefinizione/site.py +93 -0
- StreamingCommunity/Api/Site/altadefinizione/util/ScrapeSerie.py +72 -0
- StreamingCommunity/Api/Site/animeunity/__init__.py +53 -32
- StreamingCommunity/Api/Site/animeunity/film_serie.py +6 -2
- StreamingCommunity/Api/Site/animeunity/site.py +1 -11
- StreamingCommunity/Api/Site/cb01new/__init__.py +26 -14
- StreamingCommunity/Api/Site/cb01new/site.py +7 -16
- StreamingCommunity/Api/Site/ddlstreamitaly/__init__.py +26 -15
- StreamingCommunity/Api/Site/ddlstreamitaly/site.py +1 -9
- StreamingCommunity/Api/Site/guardaserie/__init__.py +23 -11
- StreamingCommunity/Api/Site/guardaserie/site.py +3 -10
- StreamingCommunity/Api/Site/mostraguarda/__init__.py +27 -7
- StreamingCommunity/Api/Site/streamingcommunity/__init__.py +50 -27
- StreamingCommunity/Api/Site/streamingcommunity/series.py +34 -12
- StreamingCommunity/Api/Site/streamingcommunity/site.py +14 -10
- StreamingCommunity/Api/Site/streamingcommunity/util/ScrapeSerie.py +38 -17
- StreamingCommunity/Api/Template/Class/SearchType.py +1 -1
- StreamingCommunity/Api/Template/Util/__init__.py +0 -1
- StreamingCommunity/Api/Template/Util/manage_ep.py +1 -0
- StreamingCommunity/Api/Template/config_loader.py +0 -4
- StreamingCommunity/Lib/Downloader/HLS/downloader.py +2 -2
- StreamingCommunity/Lib/Downloader/HLS/segments.py +1 -1
- StreamingCommunity/Lib/Downloader/MP4/downloader.py +8 -6
- StreamingCommunity/Lib/M3U8/estimator.py +3 -3
- StreamingCommunity/Upload/version.py +1 -1
- StreamingCommunity/Util/config_json.py +2 -11
- StreamingCommunity/Util/table.py +12 -2
- StreamingCommunity/__init__.py +6 -0
- StreamingCommunity/global_search.py +315 -0
- StreamingCommunity/run.py +27 -3
- {StreamingCommunity-2.9.3.dist-info → streamingcommunity-2.9.5.dist-info}/METADATA +128 -16
- streamingcommunity-2.9.5.dist-info/RECORD +80 -0
- {StreamingCommunity-2.9.3.dist-info → streamingcommunity-2.9.5.dist-info}/WHEEL +1 -1
- StreamingCommunity/Api/Template/Util/get_domain.py +0 -100
- StreamingCommunity-2.9.3.dist-info/RECORD +0 -75
- {StreamingCommunity-2.9.3.dist-info → streamingcommunity-2.9.5.dist-info}/LICENSE +0 -0
- {StreamingCommunity-2.9.3.dist-info → streamingcommunity-2.9.5.dist-info}/entry_points.txt +0 -0
- {StreamingCommunity-2.9.3.dist-info → streamingcommunity-2.9.5.dist-info}/top_level.txt +0 -0
|
@@ -12,6 +12,7 @@ from rich.prompt import Prompt
|
|
|
12
12
|
# Internal utilities
|
|
13
13
|
from StreamingCommunity.Api.Template import get_select_title
|
|
14
14
|
from StreamingCommunity.Api.Template.config_loader import site_constant
|
|
15
|
+
from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
# Logic class
|
|
@@ -30,10 +31,28 @@ msg = Prompt()
|
|
|
30
31
|
console = Console()
|
|
31
32
|
|
|
32
33
|
|
|
33
|
-
def
|
|
34
|
+
def process_search_result(select_title):
|
|
34
35
|
"""
|
|
35
|
-
|
|
36
|
+
Handles the search result and initiates the download for either a film or series.
|
|
36
37
|
"""
|
|
38
|
+
if "Serie TV" in str(select_title.type):
|
|
39
|
+
download_thread(select_title)
|
|
40
|
+
else:
|
|
41
|
+
logging.error(f"Not supported: {select_title.type}")
|
|
42
|
+
|
|
43
|
+
def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_item: dict = None):
|
|
44
|
+
"""
|
|
45
|
+
Main function of the application for search film, series and anime.
|
|
46
|
+
|
|
47
|
+
Parameters:
|
|
48
|
+
string_to_search (str, optional): String to search for
|
|
49
|
+
get_onylDatabase (bool, optional): If True, return only the database object
|
|
50
|
+
direct_item (dict, optional): Direct item to process (bypass search)
|
|
51
|
+
"""
|
|
52
|
+
if direct_item:
|
|
53
|
+
select_title = MediaItem(**direct_item)
|
|
54
|
+
process_search_result(select_title)
|
|
55
|
+
return
|
|
37
56
|
|
|
38
57
|
if string_to_search is None:
|
|
39
58
|
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):
|
|
|
41
60
|
# Search on database
|
|
42
61
|
len_database = title_search(quote_plus(string_to_search))
|
|
43
62
|
|
|
44
|
-
#
|
|
45
|
-
if
|
|
63
|
+
# If only the database is needed, return the manager
|
|
64
|
+
if get_onlyDatabase:
|
|
46
65
|
return media_search_manager
|
|
47
66
|
|
|
48
67
|
if len_database > 0:
|
|
49
|
-
|
|
50
|
-
# Select title from list
|
|
51
68
|
select_title = get_select_title(table_show_manager, media_search_manager)
|
|
52
|
-
|
|
53
|
-
# Download only film
|
|
54
|
-
if "Serie TV" in str(select_title.type):
|
|
55
|
-
download_thread(select_title)
|
|
56
|
-
|
|
57
|
-
else:
|
|
58
|
-
logging.error(f"Not supported: {select_title.type}")
|
|
69
|
+
process_search_result(select_title)
|
|
59
70
|
|
|
60
71
|
else:
|
|
72
|
+
|
|
73
|
+
# If no results are found, ask again
|
|
61
74
|
console.print(f"\n[red]Nothing matching was found for[white]: [purple]{string_to_search}")
|
|
62
|
-
|
|
63
|
-
# Retry
|
|
64
75
|
search()
|
|
@@ -18,7 +18,6 @@ from StreamingCommunity.Util.table import TVShowManager
|
|
|
18
18
|
|
|
19
19
|
# Logic class
|
|
20
20
|
from StreamingCommunity.Api.Template.config_loader import site_constant
|
|
21
|
-
from StreamingCommunity.Api.Template.Util import search_domain
|
|
22
21
|
from StreamingCommunity.Api.Template.Class.SearchType import MediaManager
|
|
23
22
|
|
|
24
23
|
|
|
@@ -42,14 +41,6 @@ def title_search(word_to_search: str) -> int:
|
|
|
42
41
|
media_search_manager.clear()
|
|
43
42
|
table_show_manager.clear()
|
|
44
43
|
|
|
45
|
-
# Check if domain is working
|
|
46
|
-
domain_to_use, base_url = search_domain(site_constant.FULL_URL)
|
|
47
|
-
|
|
48
|
-
if domain_to_use is None or base_url is None:
|
|
49
|
-
console.print("[bold red]Error: Unable to determine valid domain or base URL.[/bold red]")
|
|
50
|
-
console.print("[yellow]The service might be temporarily unavailable or the domain may have changed.[/yellow]")
|
|
51
|
-
sys.exit(1)
|
|
52
|
-
|
|
53
44
|
search_url = f"{site_constant.FULL_URL}/search/?&q={word_to_search}&quick=1&type=videobox_video&nodes=11"
|
|
54
45
|
console.print(f"[cyan]Search url: [yellow]{search_url}")
|
|
55
46
|
|
|
@@ -59,6 +50,7 @@ def title_search(word_to_search: str) -> int:
|
|
|
59
50
|
|
|
60
51
|
except Exception as e:
|
|
61
52
|
console.print(f"Site: {site_constant.SITE_NAME}, request search error: {e}")
|
|
53
|
+
return 0
|
|
62
54
|
|
|
63
55
|
# Create soup and find table
|
|
64
56
|
soup = BeautifulSoup(response.text, "html.parser")
|
|
@@ -11,6 +11,7 @@ from rich.prompt import Prompt
|
|
|
11
11
|
# Internal utilities
|
|
12
12
|
from StreamingCommunity.Api.Template import get_select_title
|
|
13
13
|
from StreamingCommunity.Api.Template.config_loader import site_constant
|
|
14
|
+
from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
# Logic class
|
|
@@ -29,10 +30,25 @@ msg = Prompt()
|
|
|
29
30
|
console = Console()
|
|
30
31
|
|
|
31
32
|
|
|
32
|
-
def
|
|
33
|
+
def process_search_result(select_title):
|
|
33
34
|
"""
|
|
34
|
-
|
|
35
|
+
Handles the search result and initiates the download for either a film or series.
|
|
35
36
|
"""
|
|
37
|
+
download_series(select_title)
|
|
38
|
+
|
|
39
|
+
def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_item: dict = None):
|
|
40
|
+
"""
|
|
41
|
+
Main function of the application for search film, series and anime.
|
|
42
|
+
|
|
43
|
+
Parameters:
|
|
44
|
+
string_to_search (str, optional): String to search for
|
|
45
|
+
get_onylDatabase (bool, optional): If True, return only the database object
|
|
46
|
+
direct_item (dict, optional): Direct item to process (bypass search)
|
|
47
|
+
"""
|
|
48
|
+
if direct_item:
|
|
49
|
+
select_title = MediaItem(**direct_item)
|
|
50
|
+
process_search_result(select_title)
|
|
51
|
+
return
|
|
36
52
|
|
|
37
53
|
if string_to_search is None:
|
|
38
54
|
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):
|
|
|
40
56
|
# Search on database
|
|
41
57
|
len_database = title_search(quote_plus(string_to_search))
|
|
42
58
|
|
|
43
|
-
#
|
|
44
|
-
if
|
|
59
|
+
# If only the database is needed, return the manager
|
|
60
|
+
if get_onlyDatabase:
|
|
45
61
|
return media_search_manager
|
|
46
62
|
|
|
47
63
|
if len_database > 0:
|
|
48
|
-
|
|
49
|
-
# Select title from list
|
|
50
64
|
select_title = get_select_title(table_show_manager, media_search_manager)
|
|
51
|
-
|
|
52
|
-
# Download only film
|
|
53
|
-
download_series(select_title)
|
|
65
|
+
process_search_result(select_title)
|
|
54
66
|
|
|
55
67
|
else:
|
|
56
|
-
console.print(f"\n[red]Nothing matching was found for[white]: [purple]{string_to_search}")
|
|
57
68
|
|
|
58
|
-
#
|
|
69
|
+
# If no results are found, ask again
|
|
70
|
+
console.print(f"\n[red]Nothing matching was found for[white]: [purple]{string_to_search}")
|
|
59
71
|
search()
|
|
@@ -16,7 +16,6 @@ from StreamingCommunity.Util.table import TVShowManager
|
|
|
16
16
|
|
|
17
17
|
# Logic class
|
|
18
18
|
from StreamingCommunity.Api.Template.config_loader import site_constant
|
|
19
|
-
from StreamingCommunity.Api.Template.Util import search_domain
|
|
20
19
|
from StreamingCommunity.Api.Template.Class.SearchType import MediaManager
|
|
21
20
|
|
|
22
21
|
|
|
@@ -41,14 +40,6 @@ def title_search(word_to_search: str) -> int:
|
|
|
41
40
|
media_search_manager.clear()
|
|
42
41
|
table_show_manager.clear()
|
|
43
42
|
|
|
44
|
-
# Check if domain is working
|
|
45
|
-
domain_to_use, base_url = search_domain(site_constant.FULL_URL)
|
|
46
|
-
|
|
47
|
-
if domain_to_use is None or base_url is None:
|
|
48
|
-
console.print("[bold red]Error: Unable to determine valid domain or base URL.[/bold red]")
|
|
49
|
-
console.print("[yellow]The service might be temporarily unavailable or the domain may have changed.[/yellow]")
|
|
50
|
-
sys.exit(1)
|
|
51
|
-
|
|
52
43
|
search_url = f"{site_constant.FULL_URL}/?story={word_to_search}&do=search&subaction=search"
|
|
53
44
|
console.print(f"[cyan]Search url: [yellow]{search_url}")
|
|
54
45
|
|
|
@@ -58,6 +49,7 @@ def title_search(word_to_search: str) -> int:
|
|
|
58
49
|
|
|
59
50
|
except Exception as e:
|
|
60
51
|
console.print(f"Site: {site_constant.SITE_NAME}, request search error: {e}")
|
|
52
|
+
return 0
|
|
61
53
|
|
|
62
54
|
# Create soup and find table
|
|
63
55
|
soup = BeautifulSoup(response.text, "html.parser")
|
|
@@ -71,7 +63,8 @@ def title_search(word_to_search: str) -> int:
|
|
|
71
63
|
|
|
72
64
|
serie_info = {
|
|
73
65
|
'name': title,
|
|
74
|
-
'url': link
|
|
66
|
+
'url': link,
|
|
67
|
+
'type': 'tv'
|
|
75
68
|
}
|
|
76
69
|
|
|
77
70
|
media_search_manager.add_media(serie_info)
|
|
@@ -5,12 +5,16 @@ from urllib.parse import quote_plus
|
|
|
5
5
|
|
|
6
6
|
# External library
|
|
7
7
|
from rich.console import Console
|
|
8
|
-
from rich.prompt import Prompt
|
|
8
|
+
from rich.prompt import Prompt
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
#
|
|
11
|
+
# Internal utilities
|
|
12
12
|
from StreamingCommunity.Api.Template.config_loader import site_constant
|
|
13
|
+
from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
|
13
14
|
from StreamingCommunity.Lib.TMBD import tmdb, Json_film
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# Logic class
|
|
14
18
|
from .film import download_film
|
|
15
19
|
|
|
16
20
|
|
|
@@ -25,16 +29,32 @@ msg = Prompt()
|
|
|
25
29
|
console = Console()
|
|
26
30
|
|
|
27
31
|
|
|
28
|
-
def
|
|
32
|
+
def process_search_result(select_title):
|
|
29
33
|
"""
|
|
30
|
-
|
|
34
|
+
Handles the search result and initiates the download for either a film or series.
|
|
31
35
|
"""
|
|
36
|
+
download_film(select_title)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_item: dict = None):
|
|
40
|
+
"""
|
|
41
|
+
Main function of the application for search film, series and anime.
|
|
42
|
+
|
|
43
|
+
Parameters:
|
|
44
|
+
string_to_search (str, optional): String to search for
|
|
45
|
+
get_onylDatabase (bool, optional): If True, return only the database object
|
|
46
|
+
direct_item (dict, optional): Direct item to process (bypass search)
|
|
47
|
+
"""
|
|
48
|
+
if direct_item:
|
|
49
|
+
select_title = MediaItem(**direct_item)
|
|
50
|
+
process_search_result(select_title)
|
|
51
|
+
return
|
|
32
52
|
|
|
33
53
|
if string_to_search is None:
|
|
34
54
|
string_to_search = msg.ask(f"\n[purple]Insert word to search in [green]{site_constant.SITE_NAME}").strip()
|
|
35
55
|
|
|
36
56
|
# Not available for the moment
|
|
37
|
-
if
|
|
57
|
+
if get_onlyDatabase:
|
|
38
58
|
return 0
|
|
39
59
|
|
|
40
60
|
# Search on database
|
|
@@ -47,7 +67,7 @@ def search(string_to_search: str = None, get_onylDatabase: bool = False):
|
|
|
47
67
|
download_film(movie_details)
|
|
48
68
|
|
|
49
69
|
else:
|
|
50
|
-
console.print(f"\n[red]Nothing matching was found for[white]: [purple]{string_to_search}")
|
|
51
70
|
|
|
52
|
-
#
|
|
71
|
+
# If no results are found, ask again
|
|
72
|
+
console.print(f"\n[red]Nothing matching was found for[white]: [purple]{string_to_search}")
|
|
53
73
|
search()
|
|
@@ -12,11 +12,12 @@ from rich.prompt import Prompt
|
|
|
12
12
|
|
|
13
13
|
# Internal utilities
|
|
14
14
|
from StreamingCommunity.Api.Template import get_select_title
|
|
15
|
+
from StreamingCommunity.Api.Template.config_loader import site_constant
|
|
16
|
+
from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
|
15
17
|
from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance
|
|
16
18
|
|
|
17
19
|
|
|
18
20
|
# Logic class
|
|
19
|
-
from StreamingCommunity.Api.Template.config_loader import site_constant
|
|
20
21
|
from .site import title_search, table_show_manager, media_search_manager
|
|
21
22
|
from .film import download_film
|
|
22
23
|
from .series import download_series
|
|
@@ -33,54 +34,76 @@ msg = Prompt()
|
|
|
33
34
|
console = Console()
|
|
34
35
|
|
|
35
36
|
|
|
36
|
-
def
|
|
37
|
+
def get_user_input(string_to_search: str = None):
|
|
37
38
|
"""
|
|
38
|
-
|
|
39
|
+
Asks the user to input a search term.
|
|
40
|
+
Handles both Telegram bot input and direct input.
|
|
39
41
|
"""
|
|
40
|
-
if
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
if string_to_search is None:
|
|
44
|
-
|
|
45
|
-
# Chiedi la scelta all'utente con il bot Telegram
|
|
42
|
+
if string_to_search is None:
|
|
43
|
+
if site_constant.TELEGRAM_BOT:
|
|
44
|
+
bot = get_bot_instance()
|
|
46
45
|
string_to_search = bot.ask(
|
|
47
46
|
"key_search",
|
|
48
|
-
f"
|
|
47
|
+
f"Enter the search term\nor type 'back' to return to the menu: ",
|
|
49
48
|
None
|
|
50
49
|
)
|
|
51
50
|
|
|
52
51
|
if string_to_search == 'back':
|
|
53
|
-
|
|
54
|
-
#
|
|
52
|
+
|
|
53
|
+
# Restart the script
|
|
55
54
|
subprocess.Popen([sys.executable] + sys.argv)
|
|
56
55
|
sys.exit()
|
|
57
|
-
|
|
56
|
+
else:
|
|
57
|
+
string_to_search = msg.ask(f"\n[purple]Insert a word to search in [green]{site_constant.SITE_NAME}").strip()
|
|
58
|
+
|
|
59
|
+
return string_to_search
|
|
60
|
+
|
|
61
|
+
def process_search_result(select_title):
|
|
62
|
+
"""
|
|
63
|
+
Handles the search result and initiates the download for either a film or series.
|
|
64
|
+
"""
|
|
65
|
+
if select_title.type == 'tv':
|
|
66
|
+
download_series(select_title)
|
|
58
67
|
else:
|
|
59
|
-
|
|
60
|
-
string_to_search = msg.ask(f"\n[purple]Insert word to search in [green]{site_constant.SITE_NAME}").strip()
|
|
68
|
+
download_film(select_title)
|
|
61
69
|
|
|
70
|
+
def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_item: dict = None):
|
|
71
|
+
"""
|
|
72
|
+
Main function of the application for search film, series and anime.
|
|
73
|
+
|
|
74
|
+
Parameters:
|
|
75
|
+
string_to_search (str, optional): String to search for
|
|
76
|
+
get_onylDatabase (bool, optional): If True, return only the database object
|
|
77
|
+
direct_item (dict, optional): Direct item to process (bypass search)
|
|
78
|
+
"""
|
|
79
|
+
if direct_item:
|
|
80
|
+
select_title = MediaItem(**direct_item)
|
|
81
|
+
process_search_result(select_title)
|
|
82
|
+
return
|
|
83
|
+
|
|
84
|
+
# Get the user input for the search term
|
|
85
|
+
string_to_search = get_user_input(string_to_search)
|
|
86
|
+
|
|
87
|
+
# Perform the database search
|
|
62
88
|
len_database = title_search(quote_plus(string_to_search))
|
|
63
89
|
|
|
64
|
-
#
|
|
65
|
-
if
|
|
90
|
+
# If only the database is needed, return the manager
|
|
91
|
+
if get_onlyDatabase:
|
|
66
92
|
return media_search_manager
|
|
67
93
|
|
|
94
|
+
if site_constant.TELEGRAM_BOT:
|
|
95
|
+
bot = get_bot_instance()
|
|
96
|
+
|
|
68
97
|
if len_database > 0:
|
|
69
|
-
|
|
70
|
-
# Select title from list
|
|
71
98
|
select_title = get_select_title(table_show_manager, media_search_manager)
|
|
72
|
-
|
|
73
|
-
if select_title.type == 'tv':
|
|
74
|
-
download_series(select_title)
|
|
75
|
-
|
|
76
|
-
else:
|
|
77
|
-
download_film(select_title)
|
|
99
|
+
process_search_result(select_title)
|
|
78
100
|
|
|
79
101
|
else:
|
|
80
102
|
console.print(f"\n[red]Nothing matching was found for[white]: [purple]{string_to_search}")
|
|
81
103
|
|
|
82
104
|
if site_constant.TELEGRAM_BOT:
|
|
83
|
-
bot.send_message(f"
|
|
105
|
+
bot.send_message(f"No results found, please try again", None)
|
|
84
106
|
|
|
85
|
-
#
|
|
107
|
+
# If no results are found, ask again
|
|
108
|
+
string_to_search = get_user_input()
|
|
86
109
|
search()
|
|
@@ -52,8 +52,15 @@ def download_video(index_season_selected: int, index_episode_selected: int, scra
|
|
|
52
52
|
start_message()
|
|
53
53
|
index_season_selected = dynamic_format_number(str(index_season_selected))
|
|
54
54
|
|
|
55
|
+
# SPECIAL: Get season number
|
|
56
|
+
season = None
|
|
57
|
+
for s in scrape_serie.seasons_manager.seasons:
|
|
58
|
+
if s.number == int(index_season_selected):
|
|
59
|
+
season = s
|
|
60
|
+
break
|
|
61
|
+
|
|
55
62
|
# Get info about episode
|
|
56
|
-
obj_episode =
|
|
63
|
+
obj_episode = season.episodes.get(index_episode_selected - 1)
|
|
57
64
|
console.print(f"[yellow]Download: [red]{index_season_selected}:{index_episode_selected} {obj_episode.name}")
|
|
58
65
|
print()
|
|
59
66
|
|
|
@@ -100,14 +107,16 @@ def download_episode(index_season_selected: int, scrape_serie: GetSerieInfo, vid
|
|
|
100
107
|
- index_season_selected (int): Index of the selected season.
|
|
101
108
|
- download_all (bool): Download all episodes in the season.
|
|
102
109
|
"""
|
|
103
|
-
|
|
104
|
-
# Clean memory of all episodes and get the number of the season
|
|
105
|
-
scrape_serie.episode_manager.clear()
|
|
106
|
-
|
|
107
|
-
# Start message and collect information about episodes
|
|
108
110
|
start_message()
|
|
109
111
|
scrape_serie.collect_info_season(index_season_selected)
|
|
110
|
-
|
|
112
|
+
|
|
113
|
+
# SPECIAL: Get season number
|
|
114
|
+
season = None
|
|
115
|
+
for s in scrape_serie.seasons_manager.seasons:
|
|
116
|
+
if s.number == index_season_selected:
|
|
117
|
+
season = s
|
|
118
|
+
break
|
|
119
|
+
episodes_count = len(season.episodes.episodes)
|
|
111
120
|
|
|
112
121
|
if download_all:
|
|
113
122
|
|
|
@@ -123,7 +132,7 @@ def download_episode(index_season_selected: int, scrape_serie: GetSerieInfo, vid
|
|
|
123
132
|
else:
|
|
124
133
|
|
|
125
134
|
# Display episodes list and manage user selection
|
|
126
|
-
last_command = display_episodes_list(
|
|
135
|
+
last_command = display_episodes_list(season.episodes.episodes)
|
|
127
136
|
list_episode_select = manage_selection(last_command, episodes_count)
|
|
128
137
|
|
|
129
138
|
try:
|
|
@@ -163,7 +172,7 @@ def download_series(select_season: MediaItem) -> None:
|
|
|
163
172
|
|
|
164
173
|
# Collect information about seasons
|
|
165
174
|
scrape_serie.collect_info_title()
|
|
166
|
-
seasons_count = scrape_serie.
|
|
175
|
+
seasons_count = len(scrape_serie.seasons_manager)
|
|
167
176
|
|
|
168
177
|
# Prompt user for season selection and download episodes
|
|
169
178
|
console.print(f"\n[green]Seasons found: [red]{seasons_count}")
|
|
@@ -176,7 +185,11 @@ def download_series(select_season: MediaItem) -> None:
|
|
|
176
185
|
|
|
177
186
|
index_season_selected = bot.ask(
|
|
178
187
|
"select_title_episode",
|
|
179
|
-
"
|
|
188
|
+
"Menu di selezione delle stagioni\n\n"
|
|
189
|
+
"- Inserisci il numero della stagione (ad esempio, 1)\n"
|
|
190
|
+
"- Inserisci * per scaricare tutte le stagioni\n"
|
|
191
|
+
"- Inserisci un intervallo di stagioni (ad esempio, 1-2) per scaricare da una stagione all'altra\n"
|
|
192
|
+
"- Inserisci (ad esempio, 3-*) per scaricare dalla stagione specificata fino alla fine della serie",
|
|
180
193
|
None
|
|
181
194
|
)
|
|
182
195
|
|
|
@@ -197,14 +210,23 @@ def download_series(select_season: MediaItem) -> None:
|
|
|
197
210
|
|
|
198
211
|
# Loop through the selected seasons and download episodes
|
|
199
212
|
for i_season in list_season_select:
|
|
213
|
+
|
|
214
|
+
# SPECIAL: Get season number
|
|
215
|
+
season = None
|
|
216
|
+
for s in scrape_serie.seasons_manager.seasons:
|
|
217
|
+
if s.number == i_season:
|
|
218
|
+
season = s
|
|
219
|
+
break
|
|
220
|
+
season_number = season.number
|
|
221
|
+
|
|
200
222
|
if len(list_season_select) > 1 or index_season_selected == "*":
|
|
201
223
|
|
|
202
224
|
# Download all episodes if multiple seasons are selected or if '*' is used
|
|
203
|
-
download_episode(
|
|
225
|
+
download_episode(season_number, scrape_serie, video_source, download_all=True)
|
|
204
226
|
else:
|
|
205
227
|
|
|
206
228
|
# Otherwise, let the user select specific episodes for the single season
|
|
207
|
-
download_episode(
|
|
229
|
+
download_episode(season_number, scrape_serie, video_source, download_all=False)
|
|
208
230
|
|
|
209
231
|
if site_constant.TELEGRAM_BOT:
|
|
210
232
|
bot.send_message(f"Finito di scaricare tutte le serie e episodi", None)
|
|
@@ -17,7 +17,6 @@ from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance
|
|
|
17
17
|
|
|
18
18
|
# Logic class
|
|
19
19
|
from StreamingCommunity.Api.Template.config_loader import site_constant
|
|
20
|
-
from StreamingCommunity.Api.Template.Util import search_domain
|
|
21
20
|
from StreamingCommunity.Api.Template.Class.SearchType import MediaManager
|
|
22
21
|
|
|
23
22
|
|
|
@@ -38,13 +37,6 @@ def title_search(title_search: str) -> int:
|
|
|
38
37
|
Returns:
|
|
39
38
|
int: The number of titles found.
|
|
40
39
|
"""
|
|
41
|
-
domain_to_use, base_url = search_domain(site_constant.FULL_URL)
|
|
42
|
-
|
|
43
|
-
if domain_to_use is None or base_url is None:
|
|
44
|
-
console.print("[bold red]Error: Unable to determine valid domain or base URL.[/bold red]")
|
|
45
|
-
console.print("[yellow]The service might be temporarily unavailable or the domain may have changed.[/yellow]")
|
|
46
|
-
sys.exit(1)
|
|
47
|
-
|
|
48
40
|
if site_constant.TELEGRAM_BOT:
|
|
49
41
|
bot = get_bot_instance()
|
|
50
42
|
|
|
@@ -60,12 +52,22 @@ def title_search(title_search: str) -> int:
|
|
|
60
52
|
|
|
61
53
|
except Exception as e:
|
|
62
54
|
console.print(f"Site: {site_constant.SITE_NAME}, request search error: {e}")
|
|
55
|
+
if site_constant.TELEGRAM_BOT:
|
|
56
|
+
bot.send_message(f"ERRORE\n\nErrore nella richiesta di ricerca:\n\n{e}", None)
|
|
57
|
+
return 0
|
|
63
58
|
|
|
64
59
|
# Prepara le scelte per l'utente
|
|
65
60
|
if site_constant.TELEGRAM_BOT:
|
|
66
61
|
choices = []
|
|
67
|
-
|
|
68
|
-
|
|
62
|
+
|
|
63
|
+
# Collect json data
|
|
64
|
+
try:
|
|
65
|
+
data = response.json().get('data', [])
|
|
66
|
+
except Exception as e:
|
|
67
|
+
console.log(f"Error parsing JSON response: {e}")
|
|
68
|
+
return 0
|
|
69
|
+
|
|
70
|
+
for i, dict_title in enumerate(data):
|
|
69
71
|
try:
|
|
70
72
|
media_search_manager.add_media({
|
|
71
73
|
'id': dict_title.get('id'),
|
|
@@ -82,6 +84,8 @@ def title_search(title_search: str) -> int:
|
|
|
82
84
|
|
|
83
85
|
except Exception as e:
|
|
84
86
|
print(f"Error parsing a film entry: {e}")
|
|
87
|
+
if site_constant.TELEGRAM_BOT:
|
|
88
|
+
bot.send_message(f"ERRORE\n\nErrore nell'analisi del film:\n\n{e}", None)
|
|
85
89
|
|
|
86
90
|
if site_constant.TELEGRAM_BOT:
|
|
87
91
|
if choices:
|
|
@@ -12,7 +12,7 @@ from bs4 import BeautifulSoup
|
|
|
12
12
|
# Internal utilities
|
|
13
13
|
from StreamingCommunity.Util.headers import get_userAgent
|
|
14
14
|
from StreamingCommunity.Util.config_json import config_manager
|
|
15
|
-
from StreamingCommunity.Api.Player.Helper.Vixcloud.util import
|
|
15
|
+
from StreamingCommunity.Api.Player.Helper.Vixcloud.util import SeasonManager
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
# Variable
|
|
@@ -22,7 +22,7 @@ max_timeout = config_manager.get_int("REQUESTS", "timeout")
|
|
|
22
22
|
class GetSerieInfo:
|
|
23
23
|
def __init__(self, url):
|
|
24
24
|
"""
|
|
25
|
-
Initialize the
|
|
25
|
+
Initialize the GetSerieInfo class for scraping TV series information.
|
|
26
26
|
|
|
27
27
|
Args:
|
|
28
28
|
- url (str): The URL of the streaming site.
|
|
@@ -31,6 +31,9 @@ class GetSerieInfo:
|
|
|
31
31
|
self.headers = {'user-agent': get_userAgent()}
|
|
32
32
|
self.url = url
|
|
33
33
|
|
|
34
|
+
# Initialize the SeasonManager
|
|
35
|
+
self.seasons_manager = SeasonManager()
|
|
36
|
+
|
|
34
37
|
def setup(self, media_id: int = None, series_name: str = None):
|
|
35
38
|
"""
|
|
36
39
|
Set up the scraper with specific media details.
|
|
@@ -41,19 +44,17 @@ class GetSerieInfo:
|
|
|
41
44
|
"""
|
|
42
45
|
self.media_id = media_id
|
|
43
46
|
|
|
44
|
-
# If series name is provided, initialize series-specific
|
|
47
|
+
# If series name is provided, initialize series-specific properties
|
|
45
48
|
if series_name is not None:
|
|
46
49
|
self.is_series = True
|
|
47
50
|
self.series_name = series_name
|
|
48
|
-
self.season_manager = None
|
|
49
|
-
self.episode_manager: EpisodeManager = EpisodeManager()
|
|
50
51
|
|
|
51
52
|
def collect_info_title(self) -> None:
|
|
52
53
|
"""
|
|
53
|
-
Retrieve
|
|
54
|
+
Retrieve general information about the TV series from the streaming site.
|
|
54
55
|
|
|
55
56
|
Raises:
|
|
56
|
-
Exception: If there's an error fetching
|
|
57
|
+
Exception: If there's an error fetching series information
|
|
57
58
|
"""
|
|
58
59
|
try:
|
|
59
60
|
response = httpx.get(
|
|
@@ -63,16 +64,30 @@ class GetSerieInfo:
|
|
|
63
64
|
)
|
|
64
65
|
response.raise_for_status()
|
|
65
66
|
|
|
66
|
-
# Extract
|
|
67
|
+
# Extract series info from JSON response
|
|
67
68
|
soup = BeautifulSoup(response.text, "html.parser")
|
|
68
69
|
json_response = json.loads(soup.find("div", {"id": "app"}).get("data-page"))
|
|
69
70
|
self.version = json_response['version']
|
|
70
|
-
|
|
71
|
-
#
|
|
72
|
-
|
|
71
|
+
|
|
72
|
+
# Extract information about available seasons
|
|
73
|
+
title_data = json_response.get("props", {}).get("title", {})
|
|
74
|
+
|
|
75
|
+
# Save general series information
|
|
76
|
+
self.title_info = title_data
|
|
77
|
+
|
|
78
|
+
# Extract available seasons and add them to SeasonManager
|
|
79
|
+
seasons_data = title_data.get("seasons", [])
|
|
80
|
+
for season_data in seasons_data:
|
|
81
|
+
self.seasons_manager.add_season({
|
|
82
|
+
'id': season_data.get('id', 0),
|
|
83
|
+
'number': season_data.get('number', 0),
|
|
84
|
+
'name': f"Season {season_data.get('number', 0)}",
|
|
85
|
+
'slug': season_data.get('slug', ''),
|
|
86
|
+
'type': title_data.get('type', '')
|
|
87
|
+
})
|
|
73
88
|
|
|
74
89
|
except Exception as e:
|
|
75
|
-
logging.error(f"Error collecting
|
|
90
|
+
logging.error(f"Error collecting series info: {e}")
|
|
76
91
|
raise
|
|
77
92
|
|
|
78
93
|
def collect_info_season(self, number_season: int) -> None:
|
|
@@ -86,6 +101,12 @@ class GetSerieInfo:
|
|
|
86
101
|
Exception: If there's an error fetching episode information
|
|
87
102
|
"""
|
|
88
103
|
try:
|
|
104
|
+
# Get the season object from SeasonManager
|
|
105
|
+
season = self.seasons_manager.get_season_by_number(number_season)
|
|
106
|
+
if not season:
|
|
107
|
+
logging.error(f"Season {number_season} not found")
|
|
108
|
+
return
|
|
109
|
+
|
|
89
110
|
response = httpx.get(
|
|
90
111
|
url=f'{self.url}/titles/{self.media_id}-{self.series_name}/stagione-{number_season}',
|
|
91
112
|
headers={
|
|
@@ -98,12 +119,12 @@ class GetSerieInfo:
|
|
|
98
119
|
response.raise_for_status()
|
|
99
120
|
|
|
100
121
|
# Extract episodes from JSON response
|
|
101
|
-
json_response = response.json().get('props').get('loadedSeason').get('episodes')
|
|
122
|
+
json_response = response.json().get('props', {}).get('loadedSeason', {}).get('episodes', [])
|
|
102
123
|
|
|
103
|
-
# Add each episode to the episode manager
|
|
124
|
+
# Add each episode to the corresponding season's episode manager
|
|
104
125
|
for dict_episode in json_response:
|
|
105
|
-
|
|
126
|
+
season.episodes.add(dict_episode)
|
|
106
127
|
|
|
107
128
|
except Exception as e:
|
|
108
|
-
logging.error(f"Error collecting
|
|
109
|
-
raise
|
|
129
|
+
logging.error(f"Error collecting episodes for season {number_season}: {e}")
|
|
130
|
+
raise
|
|
@@ -218,6 +218,7 @@ def validate_episode_selection(list_episode_select: List[int], episodes_count: i
|
|
|
218
218
|
input_episodes = input(f"Enter valid episode numbers (1-{episodes_count}): ")
|
|
219
219
|
list_episode_select = list(map(int, input_episodes.split(',')))
|
|
220
220
|
|
|
221
|
+
|
|
221
222
|
def display_episodes_list(episodes_manager) -> str:
|
|
222
223
|
"""
|
|
223
224
|
Display episodes list and handle user input.
|