StreamingCommunity 3.3.9__py3-none-any.whl → 3.4.0__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/hdplayer.py +0 -5
- StreamingCommunity/Api/Player/mediapolisvod.py +4 -13
- StreamingCommunity/Api/Player/supervideo.py +3 -8
- StreamingCommunity/Api/Player/sweetpixel.py +1 -9
- StreamingCommunity/Api/Player/vixcloud.py +5 -16
- StreamingCommunity/Api/Site/altadefinizione/film.py +4 -15
- StreamingCommunity/Api/Site/altadefinizione/site.py +2 -7
- StreamingCommunity/Api/Site/altadefinizione/util/ScrapeSerie.py +2 -7
- StreamingCommunity/Api/Site/animeunity/site.py +9 -24
- StreamingCommunity/Api/Site/animeunity/util/ScrapeSerie.py +11 -27
- StreamingCommunity/Api/Site/animeworld/film.py +4 -2
- StreamingCommunity/Api/Site/animeworld/site.py +3 -11
- StreamingCommunity/Api/Site/animeworld/util/ScrapeSerie.py +1 -4
- StreamingCommunity/Api/Site/crunchyroll/film.py +4 -5
- StreamingCommunity/Api/Site/crunchyroll/series.py +2 -3
- StreamingCommunity/Api/Site/crunchyroll/site.py +2 -9
- StreamingCommunity/Api/Site/crunchyroll/util/ScrapeSerie.py +5 -27
- StreamingCommunity/Api/Site/crunchyroll/util/get_license.py +11 -26
- StreamingCommunity/Api/Site/guardaserie/site.py +4 -12
- StreamingCommunity/Api/Site/guardaserie/util/ScrapeSerie.py +3 -10
- StreamingCommunity/Api/Site/mediasetinfinity/film.py +11 -12
- StreamingCommunity/Api/Site/mediasetinfinity/series.py +1 -2
- StreamingCommunity/Api/Site/mediasetinfinity/site.py +3 -11
- StreamingCommunity/Api/Site/mediasetinfinity/util/ScrapeSerie.py +39 -50
- StreamingCommunity/Api/Site/mediasetinfinity/util/fix_mpd.py +3 -3
- StreamingCommunity/Api/Site/mediasetinfinity/util/get_license.py +7 -25
- StreamingCommunity/Api/Site/raiplay/film.py +6 -7
- StreamingCommunity/Api/Site/raiplay/series.py +0 -2
- StreamingCommunity/Api/Site/raiplay/site.py +3 -11
- StreamingCommunity/Api/Site/raiplay/util/ScrapeSerie.py +4 -11
- StreamingCommunity/Api/Site/raiplay/util/get_license.py +3 -12
- StreamingCommunity/Api/Site/streamingcommunity/film.py +5 -16
- StreamingCommunity/Api/Site/streamingcommunity/site.py +3 -22
- StreamingCommunity/Api/Site/streamingcommunity/util/ScrapeSerie.py +11 -26
- StreamingCommunity/Api/Site/streamingwatch/__init__.py +1 -0
- StreamingCommunity/Api/Site/streamingwatch/film.py +4 -2
- StreamingCommunity/Api/Site/streamingwatch/series.py +1 -1
- StreamingCommunity/Api/Site/streamingwatch/site.py +4 -18
- StreamingCommunity/Api/Site/streamingwatch/util/ScrapeSerie.py +0 -3
- StreamingCommunity/Api/Template/config_loader.py +0 -7
- StreamingCommunity/Lib/Downloader/DASH/decrypt.py +54 -1
- StreamingCommunity/Lib/Downloader/DASH/downloader.py +131 -54
- StreamingCommunity/Lib/Downloader/DASH/parser.py +2 -3
- StreamingCommunity/Lib/Downloader/DASH/segments.py +66 -54
- StreamingCommunity/Lib/Downloader/HLS/downloader.py +31 -50
- StreamingCommunity/Lib/Downloader/HLS/segments.py +23 -28
- StreamingCommunity/Lib/FFmpeg/capture.py +37 -5
- StreamingCommunity/Lib/FFmpeg/command.py +32 -90
- StreamingCommunity/Lib/TMBD/tmdb.py +2 -4
- StreamingCommunity/TelegramHelp/config.json +0 -1
- StreamingCommunity/Upload/version.py +1 -1
- StreamingCommunity/Util/config_json.py +28 -21
- StreamingCommunity/Util/http_client.py +28 -0
- StreamingCommunity/Util/os.py +16 -6
- {streamingcommunity-3.3.9.dist-info → streamingcommunity-3.4.0.dist-info}/METADATA +1 -3
- {streamingcommunity-3.3.9.dist-info → streamingcommunity-3.4.0.dist-info}/RECORD +60 -60
- {streamingcommunity-3.3.9.dist-info → streamingcommunity-3.4.0.dist-info}/WHEEL +0 -0
- {streamingcommunity-3.3.9.dist-info → streamingcommunity-3.4.0.dist-info}/entry_points.txt +0 -0
- {streamingcommunity-3.3.9.dist-info → streamingcommunity-3.4.0.dist-info}/licenses/LICENSE +0 -0
- {streamingcommunity-3.3.9.dist-info → streamingcommunity-3.4.0.dist-info}/top_level.txt +0 -0
|
@@ -3,19 +3,12 @@
|
|
|
3
3
|
import logging
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
# External libraries
|
|
7
|
-
import httpx
|
|
8
|
-
|
|
9
|
-
|
|
10
6
|
# Internal utilities
|
|
11
7
|
from StreamingCommunity.Util.headers import get_headers
|
|
12
|
-
from StreamingCommunity.Util.
|
|
8
|
+
from StreamingCommunity.Util.http_client import create_client
|
|
13
9
|
from StreamingCommunity.Api.Player.Helper.Vixcloud.util import SeasonManager
|
|
14
10
|
|
|
15
11
|
|
|
16
|
-
# Variable
|
|
17
|
-
max_timeout = config_manager.get_int("REQUESTS", "timeout")
|
|
18
|
-
|
|
19
12
|
|
|
20
13
|
class GetSerieInfo:
|
|
21
14
|
def __init__(self, path_id: str):
|
|
@@ -32,7 +25,7 @@ class GetSerieInfo:
|
|
|
32
25
|
"""Get series info including seasons."""
|
|
33
26
|
try:
|
|
34
27
|
program_url = f"{self.base_url}/{self.path_id}"
|
|
35
|
-
response =
|
|
28
|
+
response = create_client(headers=get_headers()).get(program_url)
|
|
36
29
|
|
|
37
30
|
# If 404, content is not yet available
|
|
38
31
|
if response.status_code == 404:
|
|
@@ -88,8 +81,8 @@ class GetSerieInfo:
|
|
|
88
81
|
season = self.seasons_manager.get_season_by_number(number_season)
|
|
89
82
|
|
|
90
83
|
# Se stai leggendo questo codice spieami perche hai fatto cosi.
|
|
91
|
-
url = f"{self.base_url}/{self.path_id.replace(
|
|
92
|
-
response =
|
|
84
|
+
url = f"{self.base_url}/{self.path_id.replace('.json', '')}/{self.publishing_block_id}/{season.id}/episodes.json"
|
|
85
|
+
response = create_client(headers=get_headers()).get(url)
|
|
93
86
|
response.raise_for_status()
|
|
94
87
|
|
|
95
88
|
episodes_data = response.json()
|
|
@@ -1,20 +1,11 @@
|
|
|
1
1
|
# 16.03.25
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
# External library
|
|
5
|
-
import httpx
|
|
6
|
-
|
|
7
|
-
|
|
8
4
|
# Internal utilities
|
|
9
|
-
from StreamingCommunity.Util.
|
|
5
|
+
from StreamingCommunity.Util.http_client import create_client
|
|
10
6
|
from StreamingCommunity.Util.headers import get_headers
|
|
11
7
|
|
|
12
8
|
|
|
13
|
-
# Variable
|
|
14
|
-
MAX_TIMEOUT = config_manager.get_int("REQUESTS", "timeout")
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
9
|
def generate_license_url(mpd_id: str):
|
|
19
10
|
"""
|
|
20
11
|
Generates the URL to obtain the Widevine license.
|
|
@@ -29,8 +20,8 @@ def generate_license_url(mpd_id: str):
|
|
|
29
20
|
'cont': mpd_id,
|
|
30
21
|
'output': '62',
|
|
31
22
|
}
|
|
32
|
-
|
|
33
|
-
response =
|
|
23
|
+
|
|
24
|
+
response = create_client(headers=get_headers()).get('https://mediapolisvod.rai.it/relinker/relinkerServlet.htm', params=params)
|
|
34
25
|
response.raise_for_status()
|
|
35
26
|
|
|
36
27
|
# Extract the license URL from the response in two lines
|
|
@@ -9,8 +9,9 @@ from rich.console import Console
|
|
|
9
9
|
|
|
10
10
|
# Internal utilities
|
|
11
11
|
from StreamingCommunity.Util.os import os_manager
|
|
12
|
+
from StreamingCommunity.Util.config_json import config_manager
|
|
12
13
|
from StreamingCommunity.Util.message import start_message
|
|
13
|
-
from StreamingCommunity.TelegramHelp.telegram_bot import TelegramSession
|
|
14
|
+
from StreamingCommunity.TelegramHelp.telegram_bot import TelegramSession
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
# Logic class
|
|
@@ -25,6 +26,7 @@ from StreamingCommunity.Api.Player.vixcloud import VideoSource
|
|
|
25
26
|
|
|
26
27
|
# Variable
|
|
27
28
|
console = Console()
|
|
29
|
+
extension_output = config_manager.get("M3U8_CONVERSION", "extension")
|
|
28
30
|
|
|
29
31
|
|
|
30
32
|
def download_film(select_title: MediaItem) -> str:
|
|
@@ -38,19 +40,6 @@ def download_film(select_title: MediaItem) -> str:
|
|
|
38
40
|
Return:
|
|
39
41
|
- str: output path
|
|
40
42
|
"""
|
|
41
|
-
if site_constant.TELEGRAM_BOT:
|
|
42
|
-
bot = get_bot_instance()
|
|
43
|
-
bot.send_message(f"Download in corso:\n{select_title.name}", None)
|
|
44
|
-
|
|
45
|
-
# Viene usato per lo screen
|
|
46
|
-
console.print(f"## Download: [red]{select_title.name} ##")
|
|
47
|
-
|
|
48
|
-
# Get script_id
|
|
49
|
-
script_id = TelegramSession.get_session()
|
|
50
|
-
if script_id != "unknown":
|
|
51
|
-
TelegramSession.updateScriptId(script_id, select_title.name)
|
|
52
|
-
|
|
53
|
-
# Start message and display film information
|
|
54
43
|
start_message()
|
|
55
44
|
console.print(f"\n[bold yellow]Download:[/bold yellow] [red]{site_constant.SITE_NAME}[/red] → [cyan]{select_title.name}[/cyan] \n")
|
|
56
45
|
|
|
@@ -67,8 +56,8 @@ def download_film(select_title: MediaItem) -> str:
|
|
|
67
56
|
return None
|
|
68
57
|
|
|
69
58
|
# Define the filename and path for the downloaded film
|
|
70
|
-
title_name = os_manager.get_sanitize_file(select_title.name) +
|
|
71
|
-
mp4_path = os.path.join(site_constant.MOVIE_FOLDER, title_name.replace(
|
|
59
|
+
title_name = os_manager.get_sanitize_file(select_title.name, select_title.date) + extension_output
|
|
60
|
+
mp4_path = os.path.join(site_constant.MOVIE_FOLDER, title_name.replace(extension_output, ""))
|
|
72
61
|
|
|
73
62
|
# Download the film using the m3u8 playlist, and output filename
|
|
74
63
|
hls_process = HLS_Downloader(
|
|
@@ -4,14 +4,13 @@ import json
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
# External libraries
|
|
7
|
-
import httpx
|
|
8
7
|
from bs4 import BeautifulSoup
|
|
9
8
|
from rich.console import Console
|
|
10
9
|
|
|
11
10
|
|
|
12
11
|
# Internal utilities
|
|
13
|
-
from StreamingCommunity.Util.config_json import config_manager
|
|
14
12
|
from StreamingCommunity.Util.headers import get_userAgent
|
|
13
|
+
from StreamingCommunity.Util.http_client import create_client
|
|
15
14
|
from StreamingCommunity.Util.table import TVShowManager
|
|
16
15
|
from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance
|
|
17
16
|
|
|
@@ -25,8 +24,6 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaManager
|
|
|
25
24
|
console = Console()
|
|
26
25
|
media_search_manager = MediaManager()
|
|
27
26
|
table_show_manager = TVShowManager()
|
|
28
|
-
max_timeout = config_manager.get_int("REQUESTS", "timeout")
|
|
29
|
-
ssl_verify = config_manager.get_bool("REQUESTS", "verify")
|
|
30
27
|
|
|
31
28
|
|
|
32
29
|
def title_search(query: str) -> int:
|
|
@@ -46,13 +43,7 @@ def title_search(query: str) -> int:
|
|
|
46
43
|
table_show_manager.clear()
|
|
47
44
|
|
|
48
45
|
try:
|
|
49
|
-
response =
|
|
50
|
-
f"{site_constant.FULL_URL}/it",
|
|
51
|
-
headers={'user-agent': get_userAgent()},
|
|
52
|
-
timeout=max_timeout,
|
|
53
|
-
verify=ssl_verify,
|
|
54
|
-
follow_redirects=True
|
|
55
|
-
)
|
|
46
|
+
response = create_client(headers={'user-agent': get_userAgent()}).get(f"{site_constant.FULL_URL}/it")
|
|
56
47
|
response.raise_for_status()
|
|
57
48
|
|
|
58
49
|
soup = BeautifulSoup(response.text, 'html.parser')
|
|
@@ -66,17 +57,7 @@ def title_search(query: str) -> int:
|
|
|
66
57
|
console.print(f"[cyan]Search url: [yellow]{search_url}")
|
|
67
58
|
|
|
68
59
|
try:
|
|
69
|
-
response =
|
|
70
|
-
search_url,
|
|
71
|
-
headers = {
|
|
72
|
-
'referer': site_constant.FULL_URL,
|
|
73
|
-
'user-agent': get_userAgent(),
|
|
74
|
-
'x-inertia': 'true',
|
|
75
|
-
'x-inertia-version': version
|
|
76
|
-
},
|
|
77
|
-
timeout=max_timeout,
|
|
78
|
-
verify=ssl_verify
|
|
79
|
-
)
|
|
60
|
+
response = create_client(headers={'user-agent': get_userAgent(), 'x-inertia': 'true', 'x-inertia-version': version}).get(search_url)
|
|
80
61
|
response.raise_for_status()
|
|
81
62
|
|
|
82
63
|
except Exception as e:
|
|
@@ -5,21 +5,15 @@ import logging
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
# External libraries
|
|
8
|
-
import httpx
|
|
9
8
|
from bs4 import BeautifulSoup
|
|
10
9
|
|
|
11
10
|
|
|
12
11
|
# Internal utilities
|
|
13
|
-
from StreamingCommunity.Util.headers import
|
|
14
|
-
from StreamingCommunity.Util.
|
|
12
|
+
from StreamingCommunity.Util.headers import get_headers
|
|
13
|
+
from StreamingCommunity.Util.http_client import create_client
|
|
15
14
|
from StreamingCommunity.Api.Player.Helper.Vixcloud.util import SeasonManager
|
|
16
15
|
|
|
17
16
|
|
|
18
|
-
# Variable
|
|
19
|
-
max_timeout = config_manager.get_int("REQUESTS", "timeout")
|
|
20
|
-
ssl_verify = config_manager.get_bool("REQUESTS", "verify")
|
|
21
|
-
|
|
22
|
-
|
|
23
17
|
class GetSerieInfo:
|
|
24
18
|
def __init__(self, url, media_id: int = None, series_name: str = None):
|
|
25
19
|
"""
|
|
@@ -31,7 +25,7 @@ class GetSerieInfo:
|
|
|
31
25
|
- series_name (str, optional): Name of the TV series
|
|
32
26
|
"""
|
|
33
27
|
self.is_series = False
|
|
34
|
-
self.headers =
|
|
28
|
+
self.headers = get_headers()
|
|
35
29
|
self.url = url
|
|
36
30
|
self.media_id = media_id
|
|
37
31
|
self.seasons_manager = SeasonManager()
|
|
@@ -48,12 +42,7 @@ class GetSerieInfo:
|
|
|
48
42
|
Exception: If there's an error fetching series information
|
|
49
43
|
"""
|
|
50
44
|
try:
|
|
51
|
-
response =
|
|
52
|
-
url=f"{self.url}/titles/{self.media_id}-{self.series_name}",
|
|
53
|
-
headers=self.headers,
|
|
54
|
-
timeout=max_timeout,
|
|
55
|
-
verify=ssl_verify
|
|
56
|
-
)
|
|
45
|
+
response = create_client(headers=self.headers).get(f"{self.url}/titles/{self.media_id}-{self.series_name}")
|
|
57
46
|
response.raise_for_status()
|
|
58
47
|
|
|
59
48
|
# Extract series info from JSON response
|
|
@@ -98,17 +87,13 @@ class GetSerieInfo:
|
|
|
98
87
|
if not season:
|
|
99
88
|
logging.error(f"Season {number_season} not found")
|
|
100
89
|
return
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
},
|
|
109
|
-
timeout=max_timeout,
|
|
110
|
-
verify=ssl_verify
|
|
111
|
-
)
|
|
90
|
+
|
|
91
|
+
custom_headers = self.headers.copy()
|
|
92
|
+
custom_headers.update({
|
|
93
|
+
'x-inertia': 'true',
|
|
94
|
+
'x-inertia-version': self.version,
|
|
95
|
+
})
|
|
96
|
+
response = create_client(headers=custom_headers).get(f"{self.url}/titles/{self.media_id}-{self.series_name}/season-{number_season}")
|
|
112
97
|
|
|
113
98
|
# Extract episodes from JSON response
|
|
114
99
|
json_response = response.json().get('props', {}).get('loadedSeason', {}).get('episodes', [])
|
|
@@ -9,6 +9,7 @@ from rich.console import Console
|
|
|
9
9
|
|
|
10
10
|
# Internal utilities
|
|
11
11
|
from StreamingCommunity.Util.os import os_manager
|
|
12
|
+
from StreamingCommunity.Util.config_json import config_manager
|
|
12
13
|
from StreamingCommunity.Util.message import start_message
|
|
13
14
|
|
|
14
15
|
|
|
@@ -24,6 +25,7 @@ from StreamingCommunity.Api.Player.hdplayer import VideoSource
|
|
|
24
25
|
|
|
25
26
|
# Variable
|
|
26
27
|
console = Console()
|
|
28
|
+
extension_output = config_manager.get("M3U8_CONVERSION", "extension")
|
|
27
29
|
|
|
28
30
|
|
|
29
31
|
def download_film(select_title: MediaItem) -> str:
|
|
@@ -45,8 +47,8 @@ def download_film(select_title: MediaItem) -> str:
|
|
|
45
47
|
master_playlist = video_source.get_m3u8_url(select_title.url)
|
|
46
48
|
|
|
47
49
|
# Define the filename and path for the downloaded film
|
|
48
|
-
title_name = os_manager.get_sanitize_file(select_title.name) +
|
|
49
|
-
mp4_path = os.path.join(site_constant.MOVIE_FOLDER, title_name.replace(
|
|
50
|
+
title_name = os_manager.get_sanitize_file(select_title.name, select_title.date) + extension_output
|
|
51
|
+
mp4_path = os.path.join(site_constant.MOVIE_FOLDER, title_name.replace(extension_output, ""))
|
|
50
52
|
|
|
51
53
|
# Download the film using the m3u8 playlist, and output filename
|
|
52
54
|
hls_process = HLS_Downloader(
|
|
@@ -53,7 +53,7 @@ def download_video(index_season_selected: int, index_episode_selected: int, scra
|
|
|
53
53
|
|
|
54
54
|
# Get episode information
|
|
55
55
|
obj_episode = scrape_serie.selectEpisode(index_season_selected, index_episode_selected-1)
|
|
56
|
-
console.print(f"\n[/bold yellow] [red]{site_constant.SITE_NAME}[/red] → [cyan]{scrape_serie.series_name}[/cyan] \\ [bold magenta]{obj_episode.name}[/bold magenta] ([cyan]S{index_season_selected}E{index_episode_selected}[/cyan]) \n")
|
|
56
|
+
console.print(f"\n[bold yellow]Download:[/bold yellow] [red]{site_constant.SITE_NAME}[/red] → [cyan]{scrape_serie.series_name}[/cyan] \\ [bold magenta]{obj_episode.name}[/bold magenta] ([cyan]S{index_season_selected}E{index_episode_selected}[/cyan]) \n")
|
|
57
57
|
|
|
58
58
|
# Define filename and path for the downloaded video
|
|
59
59
|
mp4_name = f"{map_episode_title(scrape_serie.series_name, index_season_selected, index_episode_selected, obj_episode.name)}.mp4"
|
|
@@ -4,13 +4,12 @@ import re
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
# External libraries
|
|
7
|
-
import httpx
|
|
8
7
|
from bs4 import BeautifulSoup
|
|
9
8
|
from rich.console import Console
|
|
10
9
|
|
|
11
10
|
|
|
12
11
|
# Internal utilities
|
|
13
|
-
from StreamingCommunity.Util.
|
|
12
|
+
from StreamingCommunity.Util.http_client import create_client
|
|
14
13
|
from StreamingCommunity.Util.headers import get_userAgent
|
|
15
14
|
from StreamingCommunity.Util.table import TVShowManager
|
|
16
15
|
|
|
@@ -24,18 +23,13 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaManager
|
|
|
24
23
|
console = Console()
|
|
25
24
|
media_search_manager = MediaManager()
|
|
26
25
|
table_show_manager = TVShowManager()
|
|
27
|
-
max_timeout = config_manager.get_int("REQUESTS", "timeout")
|
|
28
26
|
|
|
29
27
|
|
|
30
28
|
def extract_nonce() -> str:
|
|
31
29
|
"""Extract nonce value from the page script"""
|
|
32
|
-
response =
|
|
33
|
-
site_constant.FULL_URL,
|
|
34
|
-
headers={'user-agent': get_userAgent()},
|
|
35
|
-
timeout=max_timeout
|
|
36
|
-
)
|
|
37
|
-
|
|
30
|
+
response = create_client(headers={'user-agent': get_userAgent()}).get(site_constant.FULL_URL)
|
|
38
31
|
soup = BeautifulSoup(response.content, 'html.parser')
|
|
32
|
+
|
|
39
33
|
script = soup.find('script', id='live-search-js-extra')
|
|
40
34
|
if script:
|
|
41
35
|
match = re.search(r'"admin_ajax_nonce":"([^"]+)"', script.text)
|
|
@@ -73,15 +67,7 @@ def title_search(query: str) -> int:
|
|
|
73
67
|
'_wpnonce': _wpnonce
|
|
74
68
|
}
|
|
75
69
|
|
|
76
|
-
response =
|
|
77
|
-
search_url,
|
|
78
|
-
headers={
|
|
79
|
-
'origin': site_constant.FULL_URL,
|
|
80
|
-
'user-agent': get_userAgent()
|
|
81
|
-
},
|
|
82
|
-
data=data,
|
|
83
|
-
timeout=max_timeout
|
|
84
|
-
)
|
|
70
|
+
response = create_client(headers={'origin': site_constant.FULL_URL, 'user-agent': get_userAgent()}).post(search_url, data=data)
|
|
85
71
|
response.raise_for_status()
|
|
86
72
|
soup = BeautifulSoup(response.text, 'html.parser')
|
|
87
73
|
|
|
@@ -11,12 +11,9 @@ from bs4 import BeautifulSoup
|
|
|
11
11
|
# Internal utilities
|
|
12
12
|
from StreamingCommunity.Util.headers import get_userAgent
|
|
13
13
|
from StreamingCommunity.Util.http_client import create_client
|
|
14
|
-
from StreamingCommunity.Util.config_json import config_manager
|
|
15
14
|
from StreamingCommunity.Api.Player.Helper.Vixcloud.util import SeasonManager, Episode
|
|
16
15
|
|
|
17
16
|
|
|
18
|
-
# Variable
|
|
19
|
-
max_timeout = config_manager.get_int("REQUESTS", "timeout")
|
|
20
17
|
|
|
21
18
|
|
|
22
19
|
class GetSerieInfo:
|
|
@@ -56,13 +56,6 @@ class SiteConstant:
|
|
|
56
56
|
base_path = os.path.join(base_path, self.SITE_NAME)
|
|
57
57
|
return os.path.join(base_path, config_manager.get('OUT_FOLDER', 'anime_folder_name'))
|
|
58
58
|
|
|
59
|
-
@property
|
|
60
|
-
def COOKIE(self):
|
|
61
|
-
try:
|
|
62
|
-
return config_manager.get_dict('SITE_EXTRA', self.SITE_NAME)
|
|
63
|
-
except KeyError:
|
|
64
|
-
return None
|
|
65
|
-
|
|
66
59
|
@property
|
|
67
60
|
def TELEGRAM_BOT(self):
|
|
68
61
|
return config_manager.get_bool('DEFAULT', 'telegram_bot')
|
|
@@ -3,25 +3,30 @@
|
|
|
3
3
|
import os
|
|
4
4
|
import subprocess
|
|
5
5
|
import logging
|
|
6
|
+
import threading
|
|
7
|
+
import time
|
|
6
8
|
|
|
7
9
|
|
|
8
10
|
# External libraries
|
|
9
11
|
from rich.console import Console
|
|
12
|
+
from tqdm import tqdm
|
|
10
13
|
|
|
11
14
|
|
|
12
15
|
# Internal utilities
|
|
13
16
|
from StreamingCommunity.Util.os import get_mp4decrypt_path
|
|
17
|
+
from StreamingCommunity.Util.color import Colors
|
|
14
18
|
|
|
15
19
|
# Variable
|
|
16
20
|
console = Console()
|
|
17
21
|
|
|
18
22
|
|
|
19
23
|
# NOTE!: SAREBBE MEGLIO FARLO PER OGNI FILE DURANTE IL DOWNLOAD ... MA PER ORA LO LASCIO COSI
|
|
20
|
-
def decrypt_with_mp4decrypt(encrypted_path, kid, key, output_path=None, cleanup=True):
|
|
24
|
+
def decrypt_with_mp4decrypt(type, encrypted_path, kid, key, output_path=None, cleanup=True):
|
|
21
25
|
"""
|
|
22
26
|
Decrypt an mp4/m4s file using mp4decrypt.
|
|
23
27
|
|
|
24
28
|
Args:
|
|
29
|
+
type (str): Type of file ('video' or 'audio').
|
|
25
30
|
encrypted_path (str): Path to encrypted file.
|
|
26
31
|
kid (str): Hexadecimal KID.
|
|
27
32
|
key (str): Hexadecimal key.
|
|
@@ -48,15 +53,63 @@ def decrypt_with_mp4decrypt(encrypted_path, kid, key, output_path=None, cleanup=
|
|
|
48
53
|
if not output_path:
|
|
49
54
|
output_path = os.path.splitext(encrypted_path)[0] + "_decrypted.mp4"
|
|
50
55
|
|
|
56
|
+
# Get file size for progress tracking
|
|
57
|
+
file_size = os.path.getsize(encrypted_path)
|
|
58
|
+
|
|
51
59
|
key_format = f"{kid.lower()}:{key.lower()}"
|
|
52
60
|
cmd = [get_mp4decrypt_path(), "--key", key_format, encrypted_path, output_path]
|
|
53
61
|
logging.info(f"Running command: {' '.join(cmd)}")
|
|
54
62
|
|
|
63
|
+
# Create progress bar with custom format
|
|
64
|
+
bar_format = (
|
|
65
|
+
f"{Colors.YELLOW}DECRYPT{Colors.CYAN} {type}{Colors.WHITE}: "
|
|
66
|
+
f"{Colors.MAGENTA}{{bar:40}} "
|
|
67
|
+
f"{Colors.LIGHT_GREEN}{{n_fmt}}{Colors.WHITE}/{Colors.CYAN}{{total_fmt}} "
|
|
68
|
+
f"{Colors.DARK_GRAY}[{Colors.YELLOW}{{elapsed}}{Colors.WHITE} < {Colors.CYAN}{{remaining}}{Colors.DARK_GRAY}] "
|
|
69
|
+
f"{Colors.WHITE}{{postfix}}"
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
progress_bar = tqdm(
|
|
73
|
+
total=100,
|
|
74
|
+
bar_format=bar_format,
|
|
75
|
+
unit="",
|
|
76
|
+
ncols=150
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
def monitor_output_file():
|
|
80
|
+
"""Monitor output file growth and update progress bar."""
|
|
81
|
+
last_size = 0
|
|
82
|
+
while True:
|
|
83
|
+
if os.path.exists(output_path):
|
|
84
|
+
current_size = os.path.getsize(output_path)
|
|
85
|
+
if current_size > 0:
|
|
86
|
+
progress_percent = min(int((current_size / file_size) * 100), 100)
|
|
87
|
+
progress_bar.n = progress_percent
|
|
88
|
+
progress_bar.refresh()
|
|
89
|
+
|
|
90
|
+
if current_size == last_size and current_size > 0:
|
|
91
|
+
# File stopped growing, likely finished
|
|
92
|
+
break
|
|
93
|
+
|
|
94
|
+
last_size = current_size
|
|
95
|
+
|
|
96
|
+
time.sleep(0.1)
|
|
97
|
+
|
|
98
|
+
# Start monitoring thread
|
|
99
|
+
monitor_thread = threading.Thread(target=monitor_output_file, daemon=True)
|
|
100
|
+
monitor_thread.start()
|
|
101
|
+
|
|
55
102
|
try:
|
|
56
103
|
result = subprocess.run(cmd, capture_output=True, text=True, timeout=300)
|
|
57
104
|
except Exception as e:
|
|
105
|
+
progress_bar.close()
|
|
58
106
|
console.print(f"[bold red] mp4decrypt execution failed: {e}[/bold red]")
|
|
59
107
|
return None
|
|
108
|
+
|
|
109
|
+
# Ensure progress bar reaches 100%
|
|
110
|
+
progress_bar.n = 100
|
|
111
|
+
progress_bar.refresh()
|
|
112
|
+
progress_bar.close()
|
|
60
113
|
|
|
61
114
|
if result.returncode == 0 and os.path.exists(output_path):
|
|
62
115
|
|