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,31 +3,18 @@
|
|
|
3
3
|
import logging
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
# External libraries
|
|
7
|
-
from curl_cffi import requests
|
|
8
|
-
|
|
9
|
-
|
|
10
6
|
# Internal utilities
|
|
11
|
-
from StreamingCommunity.Util.config_json import config_manager
|
|
12
7
|
from StreamingCommunity.Api.Player.Helper.Vixcloud.util import SeasonManager
|
|
8
|
+
from StreamingCommunity.Util.http_client import create_client_curl
|
|
13
9
|
from .get_license import CrunchyrollClient
|
|
14
10
|
|
|
15
11
|
|
|
16
|
-
# Variable
|
|
17
|
-
max_timeout = config_manager.get_int("REQUESTS", "timeout")
|
|
18
|
-
|
|
19
|
-
|
|
20
12
|
def get_series_seasons(series_id, headers, params):
|
|
21
13
|
"""
|
|
22
14
|
Fetches the seasons for a given series ID from Crunchyroll.
|
|
23
15
|
"""
|
|
24
16
|
url = f'https://www.crunchyroll.com/content/v2/cms/series/{series_id}/seasons'
|
|
25
|
-
response =
|
|
26
|
-
url,
|
|
27
|
-
params=params,
|
|
28
|
-
headers=headers,
|
|
29
|
-
impersonate="chrome136"
|
|
30
|
-
)
|
|
17
|
+
response = create_client_curl(headers=headers).get(url, params=params)
|
|
31
18
|
return response
|
|
32
19
|
|
|
33
20
|
|
|
@@ -36,12 +23,7 @@ def get_season_episodes(season_id, headers, params):
|
|
|
36
23
|
Fetches the episodes for a given season ID from Crunchyroll.
|
|
37
24
|
"""
|
|
38
25
|
url = f'https://www.crunchyroll.com/content/v2/cms/seasons/{season_id}/episodes'
|
|
39
|
-
response =
|
|
40
|
-
url,
|
|
41
|
-
params=params,
|
|
42
|
-
headers=headers,
|
|
43
|
-
impersonate="chrome136"
|
|
44
|
-
)
|
|
26
|
+
response = create_client_curl(headers=headers).get(url, params=params)
|
|
45
27
|
return response
|
|
46
28
|
|
|
47
29
|
|
|
@@ -137,12 +119,8 @@ class GetSerieInfo:
|
|
|
137
119
|
'ratings': 'true',
|
|
138
120
|
'locale': 'it-IT',
|
|
139
121
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
params=params,
|
|
143
|
-
headers=headers,
|
|
144
|
-
impersonate="chrome136"
|
|
145
|
-
)
|
|
122
|
+
|
|
123
|
+
response = create_client_curl(headers=headers).get(url, params=params)
|
|
146
124
|
|
|
147
125
|
if response.status_code != 200:
|
|
148
126
|
logging.warning(f"Failed to fetch audio locales for episode {episode_id}")
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# 28.07.25
|
|
2
2
|
|
|
3
3
|
from typing import Tuple, List, Dict
|
|
4
|
-
from curl_cffi import requests
|
|
5
4
|
|
|
6
5
|
|
|
7
6
|
# Internal utilities
|
|
8
7
|
from StreamingCommunity.Util.config_json import config_manager
|
|
8
|
+
from StreamingCommunity.Util.http_client import create_client_curl
|
|
9
9
|
from StreamingCommunity.Util.headers import get_userAgent
|
|
10
10
|
|
|
11
11
|
|
|
@@ -44,17 +44,13 @@ class CrunchyrollClient:
|
|
|
44
44
|
headers['authorization'] = f'Basic {PUBLIC_TOKEN}'
|
|
45
45
|
headers['content-type'] = 'application/x-www-form-urlencoded'
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
'
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
'grant_type': 'etp_rt_cookie',
|
|
55
|
-
},
|
|
56
|
-
impersonate="chrome136"
|
|
57
|
-
)
|
|
47
|
+
data = {
|
|
48
|
+
'device_id': self.device_id,
|
|
49
|
+
'device_type': 'Chrome on Windows',
|
|
50
|
+
'grant_type': 'etp_rt_cookie',
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
response = create_client_curl(headers=headers).post('https://www.crunchyroll.com/auth/v1/token', cookies=self._get_cookies(), data=data)
|
|
58
54
|
|
|
59
55
|
if response.status_code == 400:
|
|
60
56
|
print("Error 400: Please enter a correct 'etp_rt' value in config.json. You can find the value in the request headers.")
|
|
@@ -69,14 +65,8 @@ class CrunchyrollClient:
|
|
|
69
65
|
|
|
70
66
|
def get_streams(self, media_id: str) -> Dict:
|
|
71
67
|
"""Ottieni gli stream disponibili"""
|
|
72
|
-
response =
|
|
73
|
-
|
|
74
|
-
cookies=self._get_cookies(),
|
|
75
|
-
headers=self._get_headers(),
|
|
76
|
-
params={'locale': self.locale},
|
|
77
|
-
impersonate="chrome136"
|
|
78
|
-
)
|
|
79
|
-
|
|
68
|
+
response = create_client_curl(headers=self._get_headers()).get(f'https://www.crunchyroll.com/playback/v3/{media_id}/web/chrome/play', cookies=self._get_cookies(), params={'locale': self.locale})
|
|
69
|
+
|
|
80
70
|
if response.status_code == 403:
|
|
81
71
|
raise Exception("Playback is Rejected: The current subscription does not have access to this content")
|
|
82
72
|
|
|
@@ -94,12 +84,7 @@ class CrunchyrollClient:
|
|
|
94
84
|
|
|
95
85
|
def delete_active_stream(self, media_id: str, token: str) -> bool:
|
|
96
86
|
"""Elimina uno stream attivo"""
|
|
97
|
-
response =
|
|
98
|
-
f'https://www.crunchyroll.com/playback/v1/token/{media_id}/{token}',
|
|
99
|
-
cookies=self._get_cookies(),
|
|
100
|
-
headers=self._get_headers(),
|
|
101
|
-
impersonate="chrome136"
|
|
102
|
-
)
|
|
87
|
+
response = create_client_curl(headers=self._get_headers()).delete(f'https://www.crunchyroll.com/playback/v1/token/{media_id}/{token}', cookies=self._get_cookies())
|
|
103
88
|
response.raise_for_status()
|
|
104
89
|
return response.status_code in [200, 204]
|
|
105
90
|
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
# 09.06.24
|
|
2
2
|
|
|
3
|
+
|
|
3
4
|
# External libraries
|
|
4
|
-
import httpx
|
|
5
5
|
from bs4 import BeautifulSoup
|
|
6
6
|
from rich.console import Console
|
|
7
7
|
|
|
8
|
+
|
|
8
9
|
# Internal utilities
|
|
9
|
-
from StreamingCommunity.Util.config_json import config_manager
|
|
10
10
|
from StreamingCommunity.Util.headers import get_userAgent
|
|
11
|
+
from StreamingCommunity.Util.http_client import create_client
|
|
11
12
|
from StreamingCommunity.Util.table import TVShowManager
|
|
12
13
|
|
|
13
14
|
|
|
@@ -20,8 +21,6 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaManager
|
|
|
20
21
|
console = Console()
|
|
21
22
|
media_search_manager = MediaManager()
|
|
22
23
|
table_show_manager = TVShowManager()
|
|
23
|
-
max_timeout = config_manager.get_int("REQUESTS", "timeout")
|
|
24
|
-
|
|
25
24
|
|
|
26
25
|
|
|
27
26
|
def title_search(query: str) -> int:
|
|
@@ -41,15 +40,8 @@ def title_search(query: str) -> int:
|
|
|
41
40
|
console.print(f"[cyan]Search url: [yellow]{search_url}")
|
|
42
41
|
|
|
43
42
|
try:
|
|
44
|
-
response =
|
|
45
|
-
search_url,
|
|
46
|
-
headers={'user-agent': get_userAgent()},
|
|
47
|
-
timeout=max_timeout,
|
|
48
|
-
follow_redirects=True,
|
|
49
|
-
verify=False
|
|
50
|
-
)
|
|
43
|
+
response = create_client(headers={'user-agent': get_userAgent()}).get(search_url)
|
|
51
44
|
response.raise_for_status()
|
|
52
|
-
|
|
53
45
|
except Exception as e:
|
|
54
46
|
console.print(f"[red]Site: {site_constant.SITE_NAME}, request search error: {e}")
|
|
55
47
|
return 0
|
|
@@ -5,22 +5,18 @@ from typing import List, Dict
|
|
|
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
12
|
from StreamingCommunity.Util.headers import get_userAgent
|
|
14
|
-
from StreamingCommunity.Util.
|
|
13
|
+
from StreamingCommunity.Util.http_client import create_client
|
|
15
14
|
|
|
16
15
|
|
|
17
16
|
# Logic class
|
|
18
17
|
from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
|
19
18
|
|
|
20
19
|
|
|
21
|
-
# Variable
|
|
22
|
-
max_timeout = config_manager.get_int("REQUESTS", "timeout")
|
|
23
|
-
|
|
24
20
|
|
|
25
21
|
class GetSerieInfo:
|
|
26
22
|
def __init__(self, dict_serie: MediaItem) -> None:
|
|
@@ -43,8 +39,7 @@ class GetSerieInfo:
|
|
|
43
39
|
int: Number of seasons of the TV series. Returns -1 if parsing fails.
|
|
44
40
|
"""
|
|
45
41
|
try:
|
|
46
|
-
|
|
47
|
-
response = httpx.get(self.url, headers=self.headers, timeout=max_timeout, follow_redirects=True)
|
|
42
|
+
response = create_client(headers=self.headers).get(self.url)
|
|
48
43
|
response.raise_for_status()
|
|
49
44
|
|
|
50
45
|
# Find the seasons container
|
|
@@ -72,9 +67,7 @@ class GetSerieInfo:
|
|
|
72
67
|
List[Dict[str, str]]: List of dictionaries containing episode information.
|
|
73
68
|
"""
|
|
74
69
|
try:
|
|
75
|
-
|
|
76
|
-
# Make an HTTP request to the series URL
|
|
77
|
-
response = httpx.get(self.url, headers=self.headers, timeout=max_timeout, follow_redirects=True)
|
|
70
|
+
response = create_client(headers=self.headers).get(self.url)
|
|
78
71
|
response.raise_for_status()
|
|
79
72
|
|
|
80
73
|
# Parse HTML content of the page
|
|
@@ -9,7 +9,8 @@ from rich.console import Console
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
# Internal utilities
|
|
12
|
-
from StreamingCommunity.Util.
|
|
12
|
+
from StreamingCommunity.Util.config_json import config_manager
|
|
13
|
+
from StreamingCommunity.Util.os import os_manager
|
|
13
14
|
from StreamingCommunity.Util.message import start_message
|
|
14
15
|
from StreamingCommunity.Util.headers import get_headers
|
|
15
16
|
|
|
@@ -22,11 +23,12 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
|
|
22
23
|
# Player
|
|
23
24
|
from .util.fix_mpd import get_manifest
|
|
24
25
|
from StreamingCommunity import DASH_Downloader
|
|
25
|
-
from .util.get_license import
|
|
26
|
+
from .util.get_license import get_playback_url, get_tracking_info, generate_license_url
|
|
26
27
|
|
|
27
28
|
|
|
28
29
|
# Variable
|
|
29
30
|
console = Console()
|
|
31
|
+
extension_output = config_manager.get("M3U8_CONVERSION", "extension")
|
|
30
32
|
|
|
31
33
|
|
|
32
34
|
def download_film(select_title: MediaItem) -> Tuple[str, bool]:
|
|
@@ -43,21 +45,18 @@ def download_film(select_title: MediaItem) -> Tuple[str, bool]:
|
|
|
43
45
|
console.print(f"\n[bold yellow]Download:[/bold yellow] [red]{site_constant.SITE_NAME}[/red] → [cyan]{select_title.name}[/cyan] \n")
|
|
44
46
|
|
|
45
47
|
# Define the filename and path for the downloaded film
|
|
46
|
-
title_name = os_manager.get_sanitize_file(select_title.name) +
|
|
47
|
-
mp4_path = os.path.join(site_constant.MOVIE_FOLDER, title_name.replace(
|
|
48
|
+
title_name = os_manager.get_sanitize_file(select_title.name, select_title.date) + extension_output
|
|
49
|
+
mp4_path = os.path.join(site_constant.MOVIE_FOLDER, title_name.replace(extension_output, ""))
|
|
48
50
|
|
|
49
|
-
#
|
|
50
|
-
|
|
51
|
+
# Get playback URL and tracking info
|
|
52
|
+
playback_json = get_playback_url(select_title.id)
|
|
53
|
+
tracking_info = get_tracking_info(playback_json)['videos'][0]
|
|
51
54
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
license_url = generate_license_url(bearer, tracking_info)
|
|
56
|
-
mpd_url = get_manifest(tracking_info['video_src'])
|
|
55
|
+
license_url = generate_license_url(tracking_info)
|
|
56
|
+
mpd_url = get_manifest(tracking_info['url'])
|
|
57
57
|
|
|
58
58
|
# Download the episode
|
|
59
59
|
dash_process = DASH_Downloader(
|
|
60
|
-
cdm_device=get_wvd_path(),
|
|
61
60
|
license_url=license_url,
|
|
62
61
|
mpd_url=mpd_url,
|
|
63
62
|
output_path=os.path.join(mp4_path, title_name),
|
|
@@ -12,7 +12,7 @@ from rich.prompt import Prompt
|
|
|
12
12
|
# Internal utilities
|
|
13
13
|
from StreamingCommunity.Util.headers import get_headers
|
|
14
14
|
from StreamingCommunity.Util.message import start_message
|
|
15
|
-
from StreamingCommunity.Util.os import os_manager
|
|
15
|
+
from StreamingCommunity.Util.os import os_manager
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
# Logic class
|
|
@@ -70,7 +70,6 @@ def download_video(index_season_selected: int, index_episode_selected: int, scra
|
|
|
70
70
|
|
|
71
71
|
# Download the episode
|
|
72
72
|
dash_process = DASH_Downloader(
|
|
73
|
-
cdm_device=get_wvd_path(),
|
|
74
73
|
license_url=license_url,
|
|
75
74
|
mpd_url=mpd_url,
|
|
76
75
|
mpd_sub_list=tracking_info['subtitles'],
|
|
@@ -4,12 +4,11 @@ from datetime import datetime
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
# External libraries
|
|
7
|
-
import httpx
|
|
8
7
|
from rich.console import Console
|
|
9
8
|
|
|
10
9
|
|
|
11
10
|
# Internal utilities
|
|
12
|
-
from StreamingCommunity.Util.
|
|
11
|
+
from StreamingCommunity.Util.http_client import create_client
|
|
13
12
|
from StreamingCommunity.Util.table import TVShowManager
|
|
14
13
|
from StreamingCommunity.Api.Template.config_loader import site_constant
|
|
15
14
|
from StreamingCommunity.Api.Template.Class.SearchType import MediaManager
|
|
@@ -23,7 +22,6 @@ from .util.get_license import get_bearer_token
|
|
|
23
22
|
console = Console()
|
|
24
23
|
media_search_manager = MediaManager()
|
|
25
24
|
table_show_manager = TVShowManager()
|
|
26
|
-
max_timeout = config_manager.get_int("REQUESTS", "timeout")
|
|
27
25
|
|
|
28
26
|
|
|
29
27
|
def title_search(query: str) -> int:
|
|
@@ -46,15 +44,9 @@ def title_search(query: str) -> int:
|
|
|
46
44
|
'extensions': f'{{"persistedQuery":{{"version":1,"sha256Hash":"{class_mediaset_api.getHash256()}"}}}}',
|
|
47
45
|
'variables': f'{{"first":10,"property":"search","query":"{query}","uxReference":"filteredSearch"}}',
|
|
48
46
|
}
|
|
47
|
+
|
|
49
48
|
try:
|
|
50
|
-
response =
|
|
51
|
-
search_url,
|
|
52
|
-
headers=class_mediaset_api.generate_request_headers(),
|
|
53
|
-
params=params,
|
|
54
|
-
timeout=max_timeout,
|
|
55
|
-
follow_redirects=True
|
|
56
|
-
)
|
|
57
|
-
|
|
49
|
+
response = create_client(headers=class_mediaset_api.generate_request_headers()).get(search_url, params=params)
|
|
58
50
|
response.raise_for_status()
|
|
59
51
|
except Exception as e:
|
|
60
52
|
console.print(f"[red]Site: {site_constant.SITE_NAME}, request search error: {e}")
|
|
@@ -5,18 +5,14 @@ from urllib.parse import urlparse
|
|
|
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.config_json import config_manager
|
|
14
12
|
from StreamingCommunity.Util.headers import get_headers, get_userAgent
|
|
13
|
+
from StreamingCommunity.Util.http_client import create_client
|
|
15
14
|
from StreamingCommunity.Api.Player.Helper.Vixcloud.util import SeasonManager
|
|
16
15
|
|
|
17
|
-
# Variable
|
|
18
|
-
max_timeout = config_manager.get_int("REQUESTS", "timeout")
|
|
19
|
-
|
|
20
16
|
|
|
21
17
|
class GetSerieInfo:
|
|
22
18
|
def __init__(self, url):
|
|
@@ -46,20 +42,14 @@ class GetSerieInfo:
|
|
|
46
42
|
|
|
47
43
|
def _get_series_data(self):
|
|
48
44
|
"""Get series data through the API"""
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
response = client.get(
|
|
54
|
-
f'https://feed.entertainment.tv.theplatform.eu/f/{self.public_id}/mediaset-prod-all-series-v2',
|
|
55
|
-
params=params,
|
|
56
|
-
headers=headers
|
|
57
|
-
)
|
|
58
|
-
|
|
59
|
-
if response.status_code == 200:
|
|
45
|
+
try:
|
|
46
|
+
params = {'byGuid': self.serie_id}
|
|
47
|
+
response = create_client(headers=self.headers).get(f'https://feed.entertainment.tv.theplatform.eu/f/{self.public_id}/mediaset-prod-all-series-v2', params=params)
|
|
48
|
+
response.raise_for_status()
|
|
60
49
|
return response.json()
|
|
61
|
-
|
|
62
|
-
|
|
50
|
+
|
|
51
|
+
except Exception as e:
|
|
52
|
+
logging.error(f"Failed to get series data with error: {e}")
|
|
63
53
|
return None
|
|
64
54
|
|
|
65
55
|
def _process_available_seasons(self, data):
|
|
@@ -106,32 +96,30 @@ class GetSerieInfo:
|
|
|
106
96
|
|
|
107
97
|
def _extract_season_sb_ids(self, stagioni_disponibili):
|
|
108
98
|
"""Extract sb IDs from season pages"""
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
else:
|
|
134
|
-
logging.warning(f"Link 'Episodi' or 'Puntate intere' not found for season {season['tvSeasonNumber']}")
|
|
99
|
+
client = create_client()
|
|
100
|
+
|
|
101
|
+
for season in stagioni_disponibili:
|
|
102
|
+
response_page = client.get(season['page_url'], headers={'User-Agent': get_userAgent()})
|
|
103
|
+
|
|
104
|
+
print("Response for _extract_season_sb_ids:", response_page.status_code, " season index:", season['tvSeasonNumber'])
|
|
105
|
+
soup = BeautifulSoup(response_page.text, 'html.parser')
|
|
106
|
+
|
|
107
|
+
# Try first with 'Episodi', then with 'Puntate intere'
|
|
108
|
+
link = soup.find('a', string='Episodi')
|
|
109
|
+
if not link:
|
|
110
|
+
#print("Using word: Puntate intere")
|
|
111
|
+
link = soup.find('a', string='Puntate intere')
|
|
112
|
+
|
|
113
|
+
if link is None:
|
|
114
|
+
link = soup.find('a', class_ = 'titleCarousel')
|
|
115
|
+
|
|
116
|
+
if link and link.has_attr('href'):
|
|
117
|
+
if not link.string == 'Puntate intere':
|
|
118
|
+
print("Using word: Episodi")
|
|
119
|
+
|
|
120
|
+
season['sb'] = link['href'].split(',')[-1]
|
|
121
|
+
else:
|
|
122
|
+
logging.warning(f"Link 'Episodi' or 'Puntate intere' not found for season {season['tvSeasonNumber']}")
|
|
135
123
|
|
|
136
124
|
def _get_season_episodes(self, season):
|
|
137
125
|
"""Get episodes for a specific season"""
|
|
@@ -147,11 +135,11 @@ class GetSerieInfo:
|
|
|
147
135
|
'range': '0-100',
|
|
148
136
|
}
|
|
149
137
|
episode_url = f"https://feed.entertainment.tv.theplatform.eu/f/{self.public_id}/mediaset-prod-all-programs-v2"
|
|
150
|
-
|
|
151
|
-
with httpx.Client(timeout=max_timeout, follow_redirects=True) as client:
|
|
152
|
-
episode_response = client.get(episode_url, headers=episode_headers, params=params)
|
|
153
138
|
|
|
154
|
-
|
|
139
|
+
try:
|
|
140
|
+
episode_response = create_client(headers=episode_headers).get(episode_url, params=params)
|
|
141
|
+
episode_response.raise_for_status()
|
|
142
|
+
|
|
155
143
|
episode_data = episode_response.json()
|
|
156
144
|
season['episodes'] = []
|
|
157
145
|
|
|
@@ -166,8 +154,9 @@ class GetSerieInfo:
|
|
|
166
154
|
season['episodes'].append(episode_info)
|
|
167
155
|
|
|
168
156
|
print(f"Found {len(season['episodes'])} episodes for season {season['tvSeasonNumber']}")
|
|
169
|
-
|
|
170
|
-
|
|
157
|
+
|
|
158
|
+
except Exception as e:
|
|
159
|
+
logging.error(f"Failed to get episodes for season {season['tvSeasonNumber']} with error: {e}")
|
|
171
160
|
|
|
172
161
|
def collect_season(self) -> None:
|
|
173
162
|
"""
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
from urllib.parse import urlparse, urlunparse
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
#
|
|
7
|
-
import
|
|
6
|
+
# Internal utilities
|
|
7
|
+
from StreamingCommunity.Util.http_client import create_client
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
def try_mpd(url, qualities):
|
|
@@ -42,7 +42,7 @@ def try_mpd(url, qualities):
|
|
|
42
42
|
mpd_url = urlunparse(parsed._replace(path=new_path)).strip()
|
|
43
43
|
|
|
44
44
|
try:
|
|
45
|
-
r =
|
|
45
|
+
r = create_client().head(mpd_url)
|
|
46
46
|
if r.status_code == 200:
|
|
47
47
|
return mpd_url
|
|
48
48
|
|
|
@@ -7,19 +7,17 @@ import xml.etree.ElementTree as ET
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
# External library
|
|
10
|
-
import httpx
|
|
11
10
|
from bs4 import BeautifulSoup
|
|
12
11
|
from rich.console import Console
|
|
13
12
|
|
|
14
13
|
|
|
15
14
|
# Internal utilities
|
|
16
|
-
from StreamingCommunity.Util.
|
|
15
|
+
from StreamingCommunity.Util.http_client import create_client
|
|
17
16
|
from StreamingCommunity.Util.headers import get_headers, get_userAgent
|
|
18
17
|
|
|
19
18
|
|
|
20
19
|
# Variable
|
|
21
20
|
console = Console()
|
|
22
|
-
MAX_TIMEOUT = config_manager.get_int("REQUESTS", "timeout")
|
|
23
21
|
network_data = []
|
|
24
22
|
class_mediaset_api = None
|
|
25
23
|
|
|
@@ -51,17 +49,13 @@ class MediasetAPI:
|
|
|
51
49
|
'appName': self.app_name,
|
|
52
50
|
'client_id': self.client_id,
|
|
53
51
|
}
|
|
54
|
-
response =
|
|
55
|
-
'https://api-ott-prod-fe.mediaset.net/PROD/play/idm/anonymous/login/v2.0',
|
|
56
|
-
headers=self.headers,
|
|
57
|
-
json=json_data,
|
|
58
|
-
)
|
|
52
|
+
response = create_client(headers=self.headers).post('https://api-ott-prod-fe.mediaset.net/PROD/play/idm/anonymous/login/v2.0', json=json_data)
|
|
59
53
|
return response.json()['response']['beToken']
|
|
60
54
|
|
|
61
55
|
def fetch_html(self, timeout=10):
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
return
|
|
56
|
+
response = create_client(headers=self.headers).get("https://mediasetinfinity.mediaset.it/")
|
|
57
|
+
response.raise_for_status()
|
|
58
|
+
return response.text
|
|
65
59
|
|
|
66
60
|
def find_relevant_script(self, html):
|
|
67
61
|
soup = BeautifulSoup(html, "html.parser")
|
|
@@ -124,13 +118,7 @@ def get_playback_url(CONTENT_ID):
|
|
|
124
118
|
}
|
|
125
119
|
|
|
126
120
|
try:
|
|
127
|
-
response =
|
|
128
|
-
'https://api-ott-prod-fe.mediaset.net/PROD/play/playback/check/v2.0',
|
|
129
|
-
headers=headers,
|
|
130
|
-
json=json_data,
|
|
131
|
-
follow_redirects=True,
|
|
132
|
-
timeout=MAX_TIMEOUT
|
|
133
|
-
)
|
|
121
|
+
response = create_client(headers=headers).post('https://api-ott-prod-fe.mediaset.net/PROD/play/playback/check/v2.0', json=json_data)
|
|
134
122
|
response.raise_for_status()
|
|
135
123
|
resp_json = response.json()
|
|
136
124
|
|
|
@@ -255,13 +243,7 @@ def get_tracking_info(PLAYBACK_JSON):
|
|
|
255
243
|
params['publicUrl'] = PLAYBACK_JSON['publicUrl']
|
|
256
244
|
|
|
257
245
|
try:
|
|
258
|
-
response =
|
|
259
|
-
PLAYBACK_JSON['url'],
|
|
260
|
-
headers={'user-agent': get_userAgent()},
|
|
261
|
-
params=params,
|
|
262
|
-
follow_redirects=True,
|
|
263
|
-
timeout=MAX_TIMEOUT
|
|
264
|
-
)
|
|
246
|
+
response = create_client(headers={'user-agent': get_userAgent()}).get(PLAYBACK_JSON['url'], params=params)
|
|
265
247
|
response.raise_for_status()
|
|
266
248
|
|
|
267
249
|
results = parse_smil_for_media_info(response.text)
|
|
@@ -5,17 +5,16 @@ from typing import Tuple
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
# External library
|
|
8
|
-
import httpx
|
|
9
8
|
from rich.console import Console
|
|
10
9
|
|
|
11
10
|
|
|
12
11
|
# Internal utilities
|
|
13
12
|
from StreamingCommunity.Util.os import os_manager
|
|
13
|
+
from StreamingCommunity.Util.config_json import config_manager
|
|
14
14
|
from StreamingCommunity.Util.headers import get_headers
|
|
15
|
-
from StreamingCommunity.Util.
|
|
15
|
+
from StreamingCommunity.Util.http_client import create_client
|
|
16
16
|
from StreamingCommunity.Util.message import start_message
|
|
17
17
|
|
|
18
|
-
|
|
19
18
|
# Logic class
|
|
20
19
|
from .util.get_license import generate_license_url
|
|
21
20
|
from StreamingCommunity.Api.Template.config_loader import site_constant
|
|
@@ -29,6 +28,7 @@ from StreamingCommunity.Api.Player.mediapolisvod import VideoSource
|
|
|
29
28
|
|
|
30
29
|
# Variable
|
|
31
30
|
console = Console()
|
|
31
|
+
extension_output = config_manager.get("M3U8_CONVERSION", "extension")
|
|
32
32
|
|
|
33
33
|
|
|
34
34
|
def download_film(select_title: MediaItem) -> Tuple[str, bool]:
|
|
@@ -46,13 +46,13 @@ def download_film(select_title: MediaItem) -> Tuple[str, bool]:
|
|
|
46
46
|
console.print(f"\n[bold yellow]Download:[/bold yellow] [red]{site_constant.SITE_NAME}[/red] → [cyan]{select_title.name}[/cyan] \n")
|
|
47
47
|
|
|
48
48
|
# Extract m3u8 URL from the film's URL
|
|
49
|
-
response =
|
|
49
|
+
response = create_client(headers=get_headers()).get(select_title.url + ".json")
|
|
50
50
|
first_item_path = "https://www.raiplay.it" + response.json().get("first_item_path")
|
|
51
51
|
master_playlist = VideoSource.extract_m3u8_url(first_item_path)
|
|
52
52
|
|
|
53
53
|
# Define the filename and path for the downloaded film
|
|
54
|
-
mp4_name = os_manager.get_sanitize_file(select_title.name) +
|
|
55
|
-
mp4_path = os.path.join(site_constant.MOVIE_FOLDER, mp4_name.replace(
|
|
54
|
+
mp4_name = os_manager.get_sanitize_file(select_title.name, select_title.date) + extension_output
|
|
55
|
+
mp4_path = os.path.join(site_constant.MOVIE_FOLDER, mp4_name.replace(extension_output, ""))
|
|
56
56
|
|
|
57
57
|
# HLS
|
|
58
58
|
if ".mpd" not in master_playlist:
|
|
@@ -66,7 +66,6 @@ def download_film(select_title: MediaItem) -> Tuple[str, bool]:
|
|
|
66
66
|
license_url = generate_license_url(select_title.mpd_id)
|
|
67
67
|
|
|
68
68
|
dash_process = DASH_Downloader(
|
|
69
|
-
cdm_device=get_wvd_path(),
|
|
70
69
|
license_url=license_url,
|
|
71
70
|
mpd_url=master_playlist,
|
|
72
71
|
output_path=os.path.join(mp4_path, mp4_name),
|
|
@@ -11,7 +11,6 @@ from rich.prompt import Prompt
|
|
|
11
11
|
|
|
12
12
|
# Internal utilities
|
|
13
13
|
from StreamingCommunity.Util.headers import get_headers, get_userAgent
|
|
14
|
-
from StreamingCommunity.Util.os import get_wvd_path
|
|
15
14
|
from StreamingCommunity.Util.message import start_message
|
|
16
15
|
|
|
17
16
|
|
|
@@ -91,7 +90,6 @@ def download_video(index_season_selected: int, index_episode_selected: int, scra
|
|
|
91
90
|
}
|
|
92
91
|
|
|
93
92
|
dash_process = DASH_Downloader(
|
|
94
|
-
cdm_device=get_wvd_path(),
|
|
95
93
|
license_url=full_license_url.split("?")[0],
|
|
96
94
|
mpd_url=master_playlist,
|
|
97
95
|
output_path=os.path.join(mp4_path, mp4_name),
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
# 21.05.24
|
|
2
2
|
|
|
3
3
|
# External libraries
|
|
4
|
-
import httpx
|
|
5
4
|
from rich.console import Console
|
|
6
5
|
|
|
7
6
|
|
|
8
7
|
# Internal utilities
|
|
9
|
-
from StreamingCommunity.Util.
|
|
10
|
-
from StreamingCommunity.Util.
|
|
8
|
+
from StreamingCommunity.Util.headers import get_headers
|
|
9
|
+
from StreamingCommunity.Util.http_client import create_client
|
|
11
10
|
from StreamingCommunity.Util.table import TVShowManager
|
|
12
11
|
from StreamingCommunity.Api.Template.config_loader import site_constant
|
|
13
12
|
from StreamingCommunity.Api.Template.Class.SearchType import MediaManager
|
|
@@ -21,7 +20,6 @@ from .util.ScrapeSerie import GetSerieInfo
|
|
|
21
20
|
console = Console()
|
|
22
21
|
media_search_manager = MediaManager()
|
|
23
22
|
table_show_manager = TVShowManager()
|
|
24
|
-
max_timeout = config_manager.get_int("REQUESTS", "timeout")
|
|
25
23
|
|
|
26
24
|
|
|
27
25
|
def determine_media_type(item):
|
|
@@ -67,13 +65,7 @@ def title_search(query: str) -> int:
|
|
|
67
65
|
}
|
|
68
66
|
|
|
69
67
|
try:
|
|
70
|
-
response =
|
|
71
|
-
search_url,
|
|
72
|
-
headers={'user-agent': get_userAgent()},
|
|
73
|
-
json=json_data,
|
|
74
|
-
timeout=max_timeout,
|
|
75
|
-
follow_redirects=True
|
|
76
|
-
)
|
|
68
|
+
response = create_client(headers=get_headers()).post(search_url, json=json_data)
|
|
77
69
|
response.raise_for_status()
|
|
78
70
|
|
|
79
71
|
except Exception as e:
|