StreamingCommunity 3.2.5__py3-none-any.whl → 3.2.8__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/Site/altadefinizione/film.py +2 -2
- StreamingCommunity/Api/Site/altadefinizione/series.py +1 -1
- StreamingCommunity/Api/Site/animeunity/serie.py +1 -1
- StreamingCommunity/Api/Site/animeworld/film.py +1 -1
- StreamingCommunity/Api/Site/animeworld/serie.py +1 -2
- StreamingCommunity/Api/Site/cb01new/film.py +1 -1
- StreamingCommunity/Api/Site/crunchyroll/film.py +3 -4
- StreamingCommunity/Api/Site/crunchyroll/series.py +10 -6
- StreamingCommunity/Api/Site/crunchyroll/util/ScrapeSerie.py +20 -0
- StreamingCommunity/Api/Site/guardaserie/series.py +1 -2
- StreamingCommunity/Api/Site/mediasetinfinity/film.py +12 -3
- StreamingCommunity/Api/Site/mediasetinfinity/series.py +14 -6
- StreamingCommunity/Api/Site/mediasetinfinity/util/get_license.py +1 -4
- StreamingCommunity/Api/Site/raiplay/film.py +2 -2
- StreamingCommunity/Api/Site/raiplay/series.py +2 -1
- StreamingCommunity/Api/Site/streamingcommunity/film.py +1 -1
- StreamingCommunity/Api/Site/streamingcommunity/series.py +2 -2
- StreamingCommunity/Api/Site/streamingwatch/film.py +1 -1
- StreamingCommunity/Lib/Downloader/DASH/downloader.py +13 -15
- StreamingCommunity/Lib/Downloader/DASH/parser.py +1 -1
- StreamingCommunity/Lib/Downloader/HLS/downloader.py +9 -16
- StreamingCommunity/Lib/Downloader/HLS/segments.py +0 -3
- StreamingCommunity/TelegramHelp/config.json +0 -2
- StreamingCommunity/Upload/version.py +1 -1
- StreamingCommunity/Util/bento4_installer.py +191 -0
- StreamingCommunity/Util/config_json.py +1 -1
- StreamingCommunity/Util/headers.py +0 -3
- StreamingCommunity/Util/os.py +15 -46
- StreamingCommunity/__init__.py +2 -1
- StreamingCommunity/run.py +11 -10
- {streamingcommunity-3.2.5.dist-info → streamingcommunity-3.2.8.dist-info}/METADATA +4 -8
- {streamingcommunity-3.2.5.dist-info → streamingcommunity-3.2.8.dist-info}/RECORD +36 -35
- {streamingcommunity-3.2.5.dist-info → streamingcommunity-3.2.8.dist-info}/WHEEL +0 -0
- {streamingcommunity-3.2.5.dist-info → streamingcommunity-3.2.8.dist-info}/entry_points.txt +0 -0
- {streamingcommunity-3.2.5.dist-info → streamingcommunity-3.2.8.dist-info}/licenses/LICENSE +0 -0
- {streamingcommunity-3.2.5.dist-info → streamingcommunity-3.2.8.dist-info}/top_level.txt +0 -0
|
@@ -12,10 +12,9 @@ from rich.console import Console
|
|
|
12
12
|
|
|
13
13
|
# Internal utilities
|
|
14
14
|
from StreamingCommunity.Util.os import os_manager
|
|
15
|
-
from StreamingCommunity.Util.message import start_message
|
|
16
15
|
from StreamingCommunity.Util.headers import get_headers
|
|
16
|
+
from StreamingCommunity.Util.message import start_message
|
|
17
17
|
from StreamingCommunity.Util.config_json import config_manager
|
|
18
|
-
from StreamingCommunity.Lib.Downloader import HLS_Downloader
|
|
19
18
|
from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance, TelegramSession
|
|
20
19
|
|
|
21
20
|
|
|
@@ -25,6 +24,7 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
|
|
25
24
|
|
|
26
25
|
|
|
27
26
|
# Player
|
|
27
|
+
from StreamingCommunity import HLS_Downloader
|
|
28
28
|
from StreamingCommunity.Api.Player.supervideo import VideoSource
|
|
29
29
|
|
|
30
30
|
|
|
@@ -11,7 +11,6 @@ from rich.prompt import Prompt
|
|
|
11
11
|
|
|
12
12
|
# Internal utilities
|
|
13
13
|
from StreamingCommunity.Util.message import start_message
|
|
14
|
-
from StreamingCommunity.Lib.Downloader import HLS_Downloader
|
|
15
14
|
from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance, TelegramSession
|
|
16
15
|
|
|
17
16
|
|
|
@@ -29,6 +28,7 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
|
|
29
28
|
|
|
30
29
|
|
|
31
30
|
# Player
|
|
31
|
+
from StreamingCommunity import HLS_Downloader
|
|
32
32
|
from StreamingCommunity.Api.Player.supervideo import VideoSource
|
|
33
33
|
|
|
34
34
|
|
|
@@ -12,7 +12,6 @@ from rich.prompt import Prompt
|
|
|
12
12
|
# Internal utilities
|
|
13
13
|
from StreamingCommunity.Util.os import os_manager
|
|
14
14
|
from StreamingCommunity.Util.message import start_message
|
|
15
|
-
from StreamingCommunity.Lib.Downloader import MP4_downloader
|
|
16
15
|
from StreamingCommunity.TelegramHelp.telegram_bot import TelegramSession, get_bot_instance
|
|
17
16
|
|
|
18
17
|
|
|
@@ -24,6 +23,7 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
|
|
24
23
|
|
|
25
24
|
|
|
26
25
|
# Player
|
|
26
|
+
from StreamingCommunity import MP4_downloader
|
|
27
27
|
from StreamingCommunity.Api.Player.vixcloud import VideoSourceAnime
|
|
28
28
|
|
|
29
29
|
|
|
@@ -9,7 +9,6 @@ from rich.console import Console
|
|
|
9
9
|
# Internal utilities
|
|
10
10
|
from StreamingCommunity.Util.os import os_manager
|
|
11
11
|
from StreamingCommunity.Util.message import start_message
|
|
12
|
-
from StreamingCommunity.Lib.Downloader import MP4_downloader
|
|
13
12
|
|
|
14
13
|
|
|
15
14
|
# Logic class
|
|
@@ -19,6 +18,7 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
|
|
19
18
|
|
|
20
19
|
|
|
21
20
|
# Player
|
|
21
|
+
from StreamingCommunity import MP4_downloader
|
|
22
22
|
from StreamingCommunity.Api.Player.sweetpixel import VideoSource
|
|
23
23
|
|
|
24
24
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# 11.03.24
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
|
-
import logging
|
|
5
4
|
from typing import Tuple
|
|
6
5
|
|
|
7
6
|
|
|
@@ -13,7 +12,6 @@ from rich.prompt import Prompt
|
|
|
13
12
|
# Internal utilities
|
|
14
13
|
from StreamingCommunity.Util.os import os_manager
|
|
15
14
|
from StreamingCommunity.Util.message import start_message
|
|
16
|
-
from StreamingCommunity.Lib.Downloader import MP4_downloader
|
|
17
15
|
|
|
18
16
|
|
|
19
17
|
# Logic class
|
|
@@ -24,6 +22,7 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
|
|
24
22
|
|
|
25
23
|
|
|
26
24
|
# Player
|
|
25
|
+
from StreamingCommunity import MP4_downloader
|
|
27
26
|
from StreamingCommunity.Api.Player.sweetpixel import VideoSource
|
|
28
27
|
|
|
29
28
|
|
|
@@ -10,7 +10,6 @@ from rich.console import Console
|
|
|
10
10
|
# Internal utilities
|
|
11
11
|
from StreamingCommunity.Util.os import os_manager
|
|
12
12
|
from StreamingCommunity.Util.message import start_message
|
|
13
|
-
from StreamingCommunity.Lib.Downloader import HLS_Downloader
|
|
14
13
|
|
|
15
14
|
|
|
16
15
|
# Logic class
|
|
@@ -19,6 +18,7 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
|
|
19
18
|
|
|
20
19
|
|
|
21
20
|
# Player
|
|
21
|
+
from StreamingCommunity import HLS_Downloader
|
|
22
22
|
from StreamingCommunity.Api.Player.maxstream import VideoSource
|
|
23
23
|
|
|
24
24
|
|
|
@@ -9,11 +9,9 @@ from rich.console import Console
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
# Internal utilities
|
|
12
|
-
from StreamingCommunity.Util.os import os_manager
|
|
13
12
|
from StreamingCommunity.Util.message import start_message
|
|
14
13
|
from StreamingCommunity.Util.config_json import config_manager
|
|
15
|
-
from StreamingCommunity.Util.os import get_wvd_path
|
|
16
|
-
from StreamingCommunity.Lib.Downloader.DASH.downloader import DASH_Download
|
|
14
|
+
from StreamingCommunity.Util.os import os_manager, get_wvd_path
|
|
17
15
|
|
|
18
16
|
|
|
19
17
|
# Logic class
|
|
@@ -22,6 +20,7 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
|
|
22
20
|
|
|
23
21
|
|
|
24
22
|
# Player
|
|
23
|
+
from StreamingCommunity import DASH_Downloader
|
|
25
24
|
from .util.get_license import get_playback_session, get_auth_token, generate_device_id
|
|
26
25
|
|
|
27
26
|
|
|
@@ -55,7 +54,7 @@ def download_film(select_title: MediaItem) -> str:
|
|
|
55
54
|
query_params = parse_qs(parsed_url.query)
|
|
56
55
|
|
|
57
56
|
# Download the episode
|
|
58
|
-
r_proc =
|
|
57
|
+
r_proc = DASH_Downloader(
|
|
59
58
|
cdm_device=get_wvd_path(),
|
|
60
59
|
license_url='https://www.crunchyroll.com/license/v1/license/widevine',
|
|
61
60
|
mpd_url=mpd_url,
|
|
@@ -12,13 +12,11 @@ from rich.prompt import Prompt
|
|
|
12
12
|
|
|
13
13
|
# Internal utilities
|
|
14
14
|
from StreamingCommunity.Util.message import start_message
|
|
15
|
-
from StreamingCommunity.Util.os import os_manager
|
|
16
|
-
from StreamingCommunity.Util.os import get_wvd_path
|
|
17
|
-
from StreamingCommunity.Lib.Downloader.DASH.downloader import DASH_Download
|
|
15
|
+
from StreamingCommunity.Util.os import os_manager, get_wvd_path
|
|
18
16
|
|
|
19
17
|
|
|
20
18
|
# Logic class
|
|
21
|
-
from .util.ScrapeSerie import GetSerieInfo
|
|
19
|
+
from .util.ScrapeSerie import GetSerieInfo, delete_stream_episode
|
|
22
20
|
from StreamingCommunity.Api.Template.Util import (
|
|
23
21
|
manage_selection,
|
|
24
22
|
map_episode_title,
|
|
@@ -31,6 +29,7 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
|
|
31
29
|
|
|
32
30
|
|
|
33
31
|
# Player
|
|
32
|
+
from StreamingCommunity import DASH_Downloader
|
|
34
33
|
from .util.get_license import get_playback_session, get_auth_token, generate_device_id
|
|
35
34
|
|
|
36
35
|
|
|
@@ -65,12 +64,14 @@ def download_video(index_season_selected: int, index_episode_selected: int, scra
|
|
|
65
64
|
# Generate mpd and license URLs
|
|
66
65
|
url_id = obj_episode.get('url').split('/')[-1]
|
|
67
66
|
device_id = generate_device_id()
|
|
68
|
-
|
|
67
|
+
token_mpd = get_auth_token(device_id)
|
|
68
|
+
|
|
69
|
+
mpd_url, mpd_headers = get_playback_session(token_mpd, device_id, url_id)
|
|
69
70
|
parsed_url = urlparse(mpd_url)
|
|
70
71
|
query_params = parse_qs(parsed_url.query)
|
|
71
72
|
|
|
72
73
|
# Download the episode
|
|
73
|
-
r_proc =
|
|
74
|
+
r_proc = DASH_Downloader(
|
|
74
75
|
cdm_device=get_wvd_path(),
|
|
75
76
|
license_url='https://www.crunchyroll.com/license/v1/license/widevine',
|
|
76
77
|
mpd_url=mpd_url,
|
|
@@ -95,6 +96,9 @@ def download_video(index_season_selected: int, index_episode_selected: int, scra
|
|
|
95
96
|
try: os.remove(status['path'])
|
|
96
97
|
except Exception: pass
|
|
97
98
|
|
|
99
|
+
# Delete episode stream
|
|
100
|
+
delete_stream_episode(url_id, query_params['playbackGuid'][0], mpd_headers)
|
|
101
|
+
|
|
98
102
|
return status['path'], status['stopped']
|
|
99
103
|
|
|
100
104
|
def download_episode(index_season_selected: int, scrape_serie: GetSerieInfo, download_all: bool = False, episode_selection: str = None) -> None:
|
|
@@ -45,6 +45,26 @@ def get_season_episodes(season_id, headers, params):
|
|
|
45
45
|
)
|
|
46
46
|
return response
|
|
47
47
|
|
|
48
|
+
def delete_stream_episode(episode_id, stream_id, headers):
|
|
49
|
+
"""
|
|
50
|
+
Deletes a specific stream episode by episode ID and stream ID.
|
|
51
|
+
"""
|
|
52
|
+
url = f'https://www.crunchyroll.com/playback/v1/token/{episode_id}/{stream_id}'
|
|
53
|
+
headers = get_headers()
|
|
54
|
+
|
|
55
|
+
response = requests.delete(
|
|
56
|
+
url,
|
|
57
|
+
headers=headers,
|
|
58
|
+
impersonate="chrome110"
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
if response.status_code == 204:
|
|
62
|
+
return True
|
|
63
|
+
|
|
64
|
+
else:
|
|
65
|
+
logging.error(f"Failed to delete stream episode: {response.status_code} - {response.text}")
|
|
66
|
+
return False
|
|
67
|
+
|
|
48
68
|
|
|
49
69
|
class GetSerieInfo:
|
|
50
70
|
def __init__(self, series_id):
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# 13.06.24
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
|
-
import logging
|
|
5
4
|
from typing import Tuple
|
|
6
5
|
|
|
7
6
|
|
|
@@ -12,7 +11,6 @@ from rich.prompt import Prompt
|
|
|
12
11
|
|
|
13
12
|
# Internal utilities
|
|
14
13
|
from StreamingCommunity.Util.message import start_message
|
|
15
|
-
from StreamingCommunity.Lib.Downloader import HLS_Downloader
|
|
16
14
|
|
|
17
15
|
|
|
18
16
|
# Logic class
|
|
@@ -30,6 +28,7 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
|
|
30
28
|
|
|
31
29
|
# Player
|
|
32
30
|
from .util.ScrapeSerie import GetSerieInfo
|
|
31
|
+
from StreamingCommunity import HLS_Downloader
|
|
33
32
|
from StreamingCommunity.Api.Player.supervideo import VideoSource
|
|
34
33
|
|
|
35
34
|
|
|
@@ -12,7 +12,6 @@ from rich.console import Console
|
|
|
12
12
|
from StreamingCommunity.Util.os import os_manager, get_wvd_path
|
|
13
13
|
from StreamingCommunity.Util.message import start_message
|
|
14
14
|
from StreamingCommunity.Util.headers import get_headers
|
|
15
|
-
from StreamingCommunity.Lib.Downloader.DASH.downloader import DASH_Download
|
|
16
15
|
|
|
17
16
|
|
|
18
17
|
# Logic class
|
|
@@ -22,6 +21,7 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
|
|
22
21
|
|
|
23
22
|
# Player
|
|
24
23
|
from .util.fix_mpd import get_manifest
|
|
24
|
+
from StreamingCommunity import DASH_Downloader
|
|
25
25
|
from .util.get_license import get_bearer_token, get_playback_url, get_tracking_info, generate_license_url
|
|
26
26
|
|
|
27
27
|
|
|
@@ -48,14 +48,23 @@ def download_film(select_title: MediaItem) -> Tuple[str, bool]:
|
|
|
48
48
|
|
|
49
49
|
# Generate mpd and license URLs
|
|
50
50
|
bearer = get_bearer_token()
|
|
51
|
-
|
|
51
|
+
|
|
52
|
+
# Extract ID from the episode URL
|
|
53
|
+
episode_id = select_title.url.split('_')[-1]
|
|
54
|
+
if "http" in episode_id:
|
|
55
|
+
try: episode_id = select_title.url.split('/')[-1]
|
|
56
|
+
except Exception:
|
|
57
|
+
console.print(f"[red]Error:[/red] Failed to parse episode ID from URL: {select_title.url}")
|
|
58
|
+
return None, True
|
|
59
|
+
|
|
60
|
+
playback_json = get_playback_url(bearer, episode_id)
|
|
52
61
|
tracking_info = get_tracking_info(bearer, playback_json)[0]
|
|
53
62
|
|
|
54
63
|
license_url = generate_license_url(bearer, tracking_info)
|
|
55
64
|
mpd_url = get_manifest(tracking_info['video_src'])
|
|
56
65
|
|
|
57
66
|
# Download the episode
|
|
58
|
-
r_proc =
|
|
67
|
+
r_proc = DASH_Downloader(
|
|
59
68
|
cdm_device=get_wvd_path(),
|
|
60
69
|
license_url=license_url,
|
|
61
70
|
mpd_url=mpd_url,
|
|
@@ -10,11 +10,9 @@ from rich.prompt import Prompt
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
# Internal utilities
|
|
13
|
-
from StreamingCommunity.Util.message import start_message
|
|
14
|
-
from StreamingCommunity.Util.os import os_manager
|
|
15
13
|
from StreamingCommunity.Util.headers import get_headers
|
|
16
|
-
from StreamingCommunity.Util.
|
|
17
|
-
from StreamingCommunity.
|
|
14
|
+
from StreamingCommunity.Util.message import start_message
|
|
15
|
+
from StreamingCommunity.Util.os import os_manager, get_wvd_path
|
|
18
16
|
|
|
19
17
|
|
|
20
18
|
# Logic class
|
|
@@ -32,6 +30,7 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
|
|
32
30
|
|
|
33
31
|
# Player
|
|
34
32
|
from .util.fix_mpd import get_manifest
|
|
33
|
+
from StreamingCommunity import DASH_Downloader
|
|
35
34
|
from .util.get_license import get_bearer_token, get_playback_url, get_tracking_info, generate_license_url
|
|
36
35
|
|
|
37
36
|
|
|
@@ -65,14 +64,23 @@ def download_video(index_season_selected: int, index_episode_selected: int, scra
|
|
|
65
64
|
|
|
66
65
|
# Generate mpd and license URLs
|
|
67
66
|
bearer = get_bearer_token()
|
|
68
|
-
|
|
67
|
+
|
|
68
|
+
# Extract ID from the episode URL
|
|
69
|
+
episode_id = obj_episode.url.split('_')[-1]
|
|
70
|
+
if "http" in episode_id:
|
|
71
|
+
try: episode_id = obj_episode.url.split('/')[-1]
|
|
72
|
+
except Exception:
|
|
73
|
+
console.print(f"[red]Error:[/red] Failed to parse episode ID from URL: {obj_episode.url}")
|
|
74
|
+
return None, True
|
|
75
|
+
|
|
76
|
+
playback_json = get_playback_url(bearer, episode_id)
|
|
69
77
|
tracking_info = get_tracking_info(bearer, playback_json)[0]
|
|
70
78
|
|
|
71
79
|
license_url = generate_license_url(bearer, tracking_info)
|
|
72
80
|
mpd_url = get_manifest(tracking_info['video_src'])
|
|
73
81
|
|
|
74
82
|
# Download the episode
|
|
75
|
-
r_proc =
|
|
83
|
+
r_proc = DASH_Downloader(
|
|
76
84
|
cdm_device=get_wvd_path(),
|
|
77
85
|
license_url=license_url,
|
|
78
86
|
mpd_url=mpd_url,
|
|
@@ -71,10 +71,7 @@ def get_playback_url(BEARER_TOKEN, CONTENT_ID):
|
|
|
71
71
|
|
|
72
72
|
json_data = {
|
|
73
73
|
'contentId': CONTENT_ID,
|
|
74
|
-
'streamType': 'VOD'
|
|
75
|
-
'delivery': 'Streaming',
|
|
76
|
-
'createDevice': True,
|
|
77
|
-
'overrideAppName': 'web//mediasetplay-web/5.11.8-f16d93c',
|
|
74
|
+
'streamType': 'VOD'
|
|
78
75
|
}
|
|
79
76
|
|
|
80
77
|
try:
|
|
@@ -11,9 +11,8 @@ from rich.console import Console
|
|
|
11
11
|
|
|
12
12
|
# Internal utilities
|
|
13
13
|
from StreamingCommunity.Util.os import os_manager
|
|
14
|
-
from StreamingCommunity.Util.message import start_message
|
|
15
|
-
from StreamingCommunity.Lib.Downloader import HLS_Downloader
|
|
16
14
|
from StreamingCommunity.Util.headers import get_headers
|
|
15
|
+
from StreamingCommunity.Util.message import start_message
|
|
17
16
|
|
|
18
17
|
|
|
19
18
|
# Logic class
|
|
@@ -22,6 +21,7 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
|
|
22
21
|
|
|
23
22
|
|
|
24
23
|
# Player
|
|
24
|
+
from StreamingCommunity import HLS_Downloader
|
|
25
25
|
from StreamingCommunity.Api.Player.mediapolisvod import VideoSource
|
|
26
26
|
|
|
27
27
|
|
|
@@ -11,7 +11,7 @@ from rich.prompt import Prompt
|
|
|
11
11
|
|
|
12
12
|
# Internal utilities
|
|
13
13
|
from StreamingCommunity.Util.message import start_message
|
|
14
|
-
|
|
14
|
+
|
|
15
15
|
|
|
16
16
|
# Logic class
|
|
17
17
|
from .util.ScrapeSerie import GetSerieInfo
|
|
@@ -27,6 +27,7 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
# Player
|
|
30
|
+
from StreamingCommunity import HLS_Downloader
|
|
30
31
|
from StreamingCommunity.Api.Player.mediapolisvod import VideoSource
|
|
31
32
|
|
|
32
33
|
|
|
@@ -10,7 +10,6 @@ from rich.console import Console
|
|
|
10
10
|
# Internal utilities
|
|
11
11
|
from StreamingCommunity.Util.os import os_manager
|
|
12
12
|
from StreamingCommunity.Util.message import start_message
|
|
13
|
-
from StreamingCommunity.Lib.Downloader import HLS_Downloader
|
|
14
13
|
from StreamingCommunity.TelegramHelp.telegram_bot import TelegramSession, get_bot_instance
|
|
15
14
|
|
|
16
15
|
|
|
@@ -20,6 +19,7 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
|
|
20
19
|
|
|
21
20
|
|
|
22
21
|
# Player
|
|
22
|
+
from StreamingCommunity import HLS_Downloader
|
|
23
23
|
from StreamingCommunity.Api.Player.vixcloud import VideoSource
|
|
24
24
|
|
|
25
25
|
|
|
@@ -11,15 +11,14 @@ from rich.prompt import Prompt
|
|
|
11
11
|
|
|
12
12
|
# Internal utilities
|
|
13
13
|
from StreamingCommunity.Util.message import start_message
|
|
14
|
-
from StreamingCommunity.Lib.Downloader import HLS_Downloader
|
|
15
14
|
from StreamingCommunity.TelegramHelp.telegram_bot import TelegramSession, get_bot_instance
|
|
16
15
|
|
|
16
|
+
|
|
17
17
|
# Logic class
|
|
18
18
|
from .util.ScrapeSerie import GetSerieInfo
|
|
19
19
|
from StreamingCommunity.Api.Template.Util import (
|
|
20
20
|
manage_selection,
|
|
21
21
|
map_episode_title,
|
|
22
|
-
dynamic_format_number,
|
|
23
22
|
validate_selection,
|
|
24
23
|
validate_episode_selection,
|
|
25
24
|
display_episodes_list
|
|
@@ -29,6 +28,7 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
|
|
29
28
|
|
|
30
29
|
|
|
31
30
|
# Player
|
|
31
|
+
from StreamingCommunity import HLS_Downloader
|
|
32
32
|
from StreamingCommunity.Api.Player.vixcloud import VideoSource
|
|
33
33
|
|
|
34
34
|
|
|
@@ -10,7 +10,6 @@ from rich.console import Console
|
|
|
10
10
|
# Internal utilities
|
|
11
11
|
from StreamingCommunity.Util.os import os_manager
|
|
12
12
|
from StreamingCommunity.Util.message import start_message
|
|
13
|
-
from StreamingCommunity.Lib.Downloader import HLS_Downloader
|
|
14
13
|
|
|
15
14
|
|
|
16
15
|
# Logic class
|
|
@@ -19,6 +18,7 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
|
|
19
18
|
|
|
20
19
|
|
|
21
20
|
# Player
|
|
21
|
+
from StreamingCommunity import HLS_Downloader
|
|
22
22
|
from StreamingCommunity.Api.Player.hdplayer import VideoSource
|
|
23
23
|
|
|
24
24
|
|
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
4
|
import shutil
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
# External libraries
|
|
5
8
|
from rich.console import Console
|
|
6
9
|
|
|
7
10
|
|
|
8
11
|
# Internal utilities
|
|
9
12
|
from StreamingCommunity.Util.config_json import config_manager
|
|
10
|
-
from StreamingCommunity.Util.os import os_manager
|
|
11
13
|
from StreamingCommunity.Lib.FFmpeg.command import join_audios, join_video
|
|
12
14
|
|
|
13
15
|
|
|
@@ -19,17 +21,16 @@ from .cdm_helpher import get_widevine_keys
|
|
|
19
21
|
|
|
20
22
|
|
|
21
23
|
# Config
|
|
22
|
-
ENABLE_AUDIO = config_manager.get_bool('M3U8_DOWNLOAD', 'download_audio')
|
|
23
24
|
DOWNLOAD_SPECIFIC_AUDIO = config_manager.get_list('M3U8_DOWNLOAD', 'specific_list_audio')
|
|
24
|
-
CLEANUP_TMP = config_manager.get_bool('M3U8_DOWNLOAD', 'cleanup_tmp_folder')
|
|
25
25
|
FILTER_CUSTOM_REOLUTION = str(config_manager.get('M3U8_PARSER', 'force_resolution')).strip().lower()
|
|
26
|
+
CLEANUP_TMP = config_manager.get_bool('M3U8_DOWNLOAD', 'cleanup_tmp_folder')
|
|
26
27
|
|
|
27
28
|
|
|
28
29
|
# Variable
|
|
29
30
|
console = Console()
|
|
30
31
|
|
|
31
32
|
|
|
32
|
-
class
|
|
33
|
+
class DASH_Downloader:
|
|
33
34
|
def __init__(self, cdm_device, license_url, mpd_url, output_path):
|
|
34
35
|
self.cdm_device = cdm_device
|
|
35
36
|
self.license_url = license_url
|
|
@@ -69,17 +70,14 @@ class DASH_Download:
|
|
|
69
70
|
)
|
|
70
71
|
self.selected_video = selected_video
|
|
71
72
|
|
|
72
|
-
# Audio info
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
self.selected_audio = selected_audio
|
|
81
|
-
else:
|
|
82
|
-
self.selected_audio = None
|
|
73
|
+
# Audio info
|
|
74
|
+
selected_audio, list_available_audio_langs, filter_custom_audio, downloadable_audio = self.parser.select_audio(DOWNLOAD_SPECIFIC_AUDIO)
|
|
75
|
+
console.print(
|
|
76
|
+
f"[cyan bold]Audio [/cyan bold] [green]Available:[/green] [purple]{', '.join(list_available_audio_langs)}[/purple] | "
|
|
77
|
+
f"[red]Set:[/red] [purple]{filter_custom_audio}[/purple] | "
|
|
78
|
+
f"[yellow]Downloadable:[/yellow] [purple]{downloadable_audio}[/purple]"
|
|
79
|
+
)
|
|
80
|
+
self.selected_audio = selected_audio
|
|
83
81
|
|
|
84
82
|
def get_representation_by_type(self, typ):
|
|
85
83
|
if typ == "video":
|
|
@@ -61,7 +61,7 @@ class MPDParser:
|
|
|
61
61
|
self.base_url = mpd_url.rsplit('/', 1)[0] + '/'
|
|
62
62
|
|
|
63
63
|
def parse(self, custom_headers):
|
|
64
|
-
response = httpx.get(self.mpd_url, headers=custom_headers, timeout=max_timeout
|
|
64
|
+
response = httpx.get(self.mpd_url, headers=custom_headers, timeout=max_timeout)
|
|
65
65
|
response.raise_for_status()
|
|
66
66
|
|
|
67
67
|
root = ET.fromstring(response.content)
|
|
@@ -17,7 +17,7 @@ from rich.panel import Panel
|
|
|
17
17
|
# Internal utilities
|
|
18
18
|
from StreamingCommunity.Util.config_json import config_manager
|
|
19
19
|
from StreamingCommunity.Util.headers import get_userAgent
|
|
20
|
-
from StreamingCommunity.Util.os import
|
|
20
|
+
from StreamingCommunity.Util.os import os_manager, internet_manager
|
|
21
21
|
from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance
|
|
22
22
|
|
|
23
23
|
|
|
@@ -33,11 +33,9 @@ from .segments import M3U8_Segments
|
|
|
33
33
|
|
|
34
34
|
|
|
35
35
|
# Config
|
|
36
|
-
ENABLE_AUDIO = config_manager.get_bool('M3U8_DOWNLOAD', 'download_audio')
|
|
37
36
|
ENABLE_SUBTITLE = config_manager.get_bool('M3U8_DOWNLOAD', 'download_subtitle')
|
|
38
37
|
DOWNLOAD_SPECIFIC_AUDIO = config_manager.get_list('M3U8_DOWNLOAD', 'specific_list_audio')
|
|
39
38
|
DOWNLOAD_SPECIFIC_SUBTITLE = config_manager.get_list('M3U8_DOWNLOAD', 'specific_list_subtitles')
|
|
40
|
-
MERGE_AUDIO = config_manager.get_bool('M3U8_DOWNLOAD', 'merge_audio')
|
|
41
39
|
MERGE_SUBTITLE = config_manager.get_bool('M3U8_DOWNLOAD', 'merge_subs')
|
|
42
40
|
CLEANUP_TMP = config_manager.get_bool('M3U8_DOWNLOAD', 'cleanup_tmp_folder')
|
|
43
41
|
FILTER_CUSTOM_REOLUTION = str(config_manager.get('M3U8_PARSER', 'force_resolution')).strip().lower()
|
|
@@ -65,6 +63,7 @@ class HLSClient:
|
|
|
65
63
|
Response content/text or None if all retries fail
|
|
66
64
|
"""
|
|
67
65
|
client = httpx.Client(headers=self.headers, timeout=MAX_TIMEOUT, follow_redirects=True)
|
|
66
|
+
|
|
68
67
|
for attempt in range(RETRY_LIMIT):
|
|
69
68
|
try:
|
|
70
69
|
response = client.get(url)
|
|
@@ -95,11 +94,6 @@ class PathManager:
|
|
|
95
94
|
Ensures output path is valid and follows expected format.
|
|
96
95
|
Creates a hash-based filename if no path is provided.
|
|
97
96
|
"""
|
|
98
|
-
if not path:
|
|
99
|
-
root = config_manager.get('OUT_FOLDER', 'root_path')
|
|
100
|
-
hash_name = compute_sha1_hash(self.m3u8_url) + ".mp4"
|
|
101
|
-
return os.path.join(root, "undefined", hash_name)
|
|
102
|
-
|
|
103
97
|
if not path.endswith(".mp4"):
|
|
104
98
|
path += ".mp4"
|
|
105
99
|
|
|
@@ -171,12 +165,11 @@ class M3U8Manager:
|
|
|
171
165
|
logging.error("Resolution not recognized.")
|
|
172
166
|
self.video_url, self.video_res = self.parser._video.get_best_uri()
|
|
173
167
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
self.
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
]
|
|
168
|
+
# Audio info
|
|
169
|
+
self.audio_streams = [
|
|
170
|
+
s for s in (self.parser._audio.get_all_uris_and_names() or [])
|
|
171
|
+
if s.get('language') in DOWNLOAD_SPECIFIC_AUDIO
|
|
172
|
+
]
|
|
180
173
|
|
|
181
174
|
self.sub_streams = []
|
|
182
175
|
if ENABLE_SUBTITLE:
|
|
@@ -308,8 +301,8 @@ class DownloadManager:
|
|
|
308
301
|
Downloads all selected streams (video, audio, subtitles).
|
|
309
302
|
"""
|
|
310
303
|
return_stopped = False
|
|
311
|
-
|
|
312
304
|
video_file = os.path.join(self.temp_dir, 'video', '0.ts')
|
|
305
|
+
|
|
313
306
|
if not os.path.exists(video_file):
|
|
314
307
|
if self.download_video(video_url):
|
|
315
308
|
if not return_stopped:
|
|
@@ -374,7 +367,7 @@ class MergeManager:
|
|
|
374
367
|
)
|
|
375
368
|
|
|
376
369
|
else:
|
|
377
|
-
if
|
|
370
|
+
if self.audio_streams:
|
|
378
371
|
audio_tracks = [{
|
|
379
372
|
'path': os.path.join(self.temp_dir, 'audio', a['language'], '0.ts'),
|
|
380
373
|
'name': a['language']
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# 18.07.25
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import platform
|
|
5
|
+
import logging
|
|
6
|
+
import shutil
|
|
7
|
+
import zipfile
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
# External library
|
|
11
|
+
import requests
|
|
12
|
+
from rich.console import Console
|
|
13
|
+
from rich.progress import Progress, SpinnerColumn, BarColumn, TextColumn, TimeRemainingColumn
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
# Variable
|
|
17
|
+
console = Console()
|
|
18
|
+
|
|
19
|
+
BENTO4_CONFIGURATION = {
|
|
20
|
+
'windows': {
|
|
21
|
+
'base_dir': lambda home: os.path.join(os.path.splitdrive(home)[0] + os.sep, 'binary'),
|
|
22
|
+
'download_url': 'https://www.bok.net/Bento4/binaries/Bento4-SDK-{version}.{platform}.zip',
|
|
23
|
+
'versions': {
|
|
24
|
+
'x64': 'x86_64-microsoft-win32',
|
|
25
|
+
'x86': 'x86-microsoft-win32-vs2010',
|
|
26
|
+
},
|
|
27
|
+
'executables': ['mp4decrypt.exe']
|
|
28
|
+
},
|
|
29
|
+
'darwin': {
|
|
30
|
+
'base_dir': lambda home: os.path.join(home, 'Applications', 'binary'),
|
|
31
|
+
'download_url': 'https://www.bok.net/Bento4/binaries/Bento4-SDK-{version}.{platform}.zip',
|
|
32
|
+
'versions': {
|
|
33
|
+
'x64': 'universal-apple-macosx',
|
|
34
|
+
'arm64': 'universal-apple-macosx'
|
|
35
|
+
},
|
|
36
|
+
'executables': ['mp4decrypt']
|
|
37
|
+
},
|
|
38
|
+
'linux': {
|
|
39
|
+
'base_dir': lambda home: os.path.join(home, '.local', 'bin', 'binary'),
|
|
40
|
+
'download_url': 'https://www.bok.net/Bento4/binaries/Bento4-SDK-{version}.{platform}.zip',
|
|
41
|
+
'versions': {
|
|
42
|
+
'x64': 'x86_64-unknown-linux',
|
|
43
|
+
'x86': 'x86-unknown-linux',
|
|
44
|
+
'arm64': 'x86_64-unknown-linux'
|
|
45
|
+
},
|
|
46
|
+
'executables': ['mp4decrypt']
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class Bento4Downloader:
|
|
52
|
+
def __init__(self):
|
|
53
|
+
self.os_name = platform.system().lower()
|
|
54
|
+
self.arch = self._detect_arch()
|
|
55
|
+
self.home_dir = os.path.expanduser('~')
|
|
56
|
+
self.base_dir = BENTO4_CONFIGURATION[self.os_name]['base_dir'](self.home_dir)
|
|
57
|
+
self.version = "1-6-0-641" # Latest stable version as of Nov 2023
|
|
58
|
+
os.makedirs(self.base_dir, exist_ok=True)
|
|
59
|
+
|
|
60
|
+
def _detect_arch(self) -> str:
|
|
61
|
+
machine = platform.machine().lower()
|
|
62
|
+
arch_map = {
|
|
63
|
+
'amd64': 'x64',
|
|
64
|
+
'x86_64': 'x64',
|
|
65
|
+
'x64': 'x64',
|
|
66
|
+
'arm64': 'arm64',
|
|
67
|
+
'aarch64': 'arm64',
|
|
68
|
+
'x86': 'x86',
|
|
69
|
+
'i386': 'x86',
|
|
70
|
+
'i686': 'x86'
|
|
71
|
+
}
|
|
72
|
+
return arch_map.get(machine, machine)
|
|
73
|
+
|
|
74
|
+
def _download_file(self, url: str, destination: str) -> bool:
|
|
75
|
+
try:
|
|
76
|
+
response = requests.get(url, stream=True)
|
|
77
|
+
response.raise_for_status()
|
|
78
|
+
total_size = int(response.headers.get('content-length', 0))
|
|
79
|
+
|
|
80
|
+
with open(destination, 'wb') as file, \
|
|
81
|
+
Progress(
|
|
82
|
+
SpinnerColumn(),
|
|
83
|
+
TextColumn("[progress.description]{task.description}"),
|
|
84
|
+
BarColumn(),
|
|
85
|
+
TextColumn("[progress.percentage]{task.percentage:>3.0f}%"),
|
|
86
|
+
TimeRemainingColumn()
|
|
87
|
+
) as progress:
|
|
88
|
+
|
|
89
|
+
download_task = progress.add_task("[green]Downloading Bento4", total=total_size)
|
|
90
|
+
for chunk in response.iter_content(chunk_size=8192):
|
|
91
|
+
size = file.write(chunk)
|
|
92
|
+
progress.update(download_task, advance=size)
|
|
93
|
+
|
|
94
|
+
return True
|
|
95
|
+
|
|
96
|
+
except Exception as e:
|
|
97
|
+
logging.error(f"Download error: {e}")
|
|
98
|
+
return False
|
|
99
|
+
|
|
100
|
+
def _extract_executables(self, zip_path: str) -> list:
|
|
101
|
+
try:
|
|
102
|
+
extracted_files = []
|
|
103
|
+
config = BENTO4_CONFIGURATION[self.os_name]
|
|
104
|
+
executables = config['executables']
|
|
105
|
+
|
|
106
|
+
with zipfile.ZipFile(zip_path, 'r') as zip_ref:
|
|
107
|
+
for zip_info in zip_ref.filelist:
|
|
108
|
+
for executable in executables:
|
|
109
|
+
if zip_info.filename.endswith(executable):
|
|
110
|
+
|
|
111
|
+
# Extract to base directory
|
|
112
|
+
zip_ref.extract(zip_info, self.base_dir)
|
|
113
|
+
src_path = os.path.join(self.base_dir, zip_info.filename)
|
|
114
|
+
dst_path = os.path.join(self.base_dir, executable)
|
|
115
|
+
|
|
116
|
+
# Move to final location
|
|
117
|
+
shutil.move(src_path, dst_path)
|
|
118
|
+
os.chmod(dst_path, 0o755)
|
|
119
|
+
extracted_files.append(dst_path)
|
|
120
|
+
|
|
121
|
+
# Clean up intermediate directories
|
|
122
|
+
parts = zip_info.filename.split('/')
|
|
123
|
+
if len(parts) > 1:
|
|
124
|
+
shutil.rmtree(os.path.join(self.base_dir, parts[0]))
|
|
125
|
+
|
|
126
|
+
return extracted_files
|
|
127
|
+
|
|
128
|
+
except Exception as e:
|
|
129
|
+
logging.error(f"Extraction error: {e}")
|
|
130
|
+
return []
|
|
131
|
+
|
|
132
|
+
def download(self) -> list:
|
|
133
|
+
try:
|
|
134
|
+
config = BENTO4_CONFIGURATION[self.os_name]
|
|
135
|
+
platform_str = config['versions'].get(self.arch)
|
|
136
|
+
|
|
137
|
+
if not platform_str:
|
|
138
|
+
raise ValueError(f"Unsupported architecture: {self.arch}")
|
|
139
|
+
|
|
140
|
+
download_url = config['download_url'].format(
|
|
141
|
+
version=self.version,
|
|
142
|
+
platform=platform_str
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
zip_path = os.path.join(self.base_dir, "bento4.zip")
|
|
146
|
+
console.print(f"[bold blue]Downloading Bento4 from {download_url}[/]")
|
|
147
|
+
|
|
148
|
+
if self._download_file(download_url, zip_path):
|
|
149
|
+
extracted_files = self._extract_executables(zip_path)
|
|
150
|
+
os.remove(zip_path)
|
|
151
|
+
|
|
152
|
+
if extracted_files:
|
|
153
|
+
console.print("[bold green]Bento4 successfully installed[/]")
|
|
154
|
+
return extracted_files
|
|
155
|
+
|
|
156
|
+
raise Exception("Failed to install Bento4")
|
|
157
|
+
|
|
158
|
+
except Exception as e:
|
|
159
|
+
logging.error(f"Error downloading Bento4: {e}")
|
|
160
|
+
console.print(f"[bold red]Error downloading Bento4: {str(e)}[/]")
|
|
161
|
+
return []
|
|
162
|
+
|
|
163
|
+
def check_mp4decrypt() -> str:
|
|
164
|
+
"""Check for mp4decrypt in the system and download if not found."""
|
|
165
|
+
try:
|
|
166
|
+
# First check if mp4decrypt is in PATH
|
|
167
|
+
mp4decrypt = "mp4decrypt.exe" if platform.system().lower() == "windows" else "mp4decrypt"
|
|
168
|
+
mp4decrypt_path = shutil.which(mp4decrypt)
|
|
169
|
+
|
|
170
|
+
if mp4decrypt_path:
|
|
171
|
+
return mp4decrypt_path
|
|
172
|
+
|
|
173
|
+
# If not found, check in binary directory
|
|
174
|
+
downloader = Bento4Downloader()
|
|
175
|
+
base_dir = downloader.base_dir
|
|
176
|
+
local_path = os.path.join(base_dir, mp4decrypt)
|
|
177
|
+
|
|
178
|
+
if os.path.exists(local_path):
|
|
179
|
+
return local_path
|
|
180
|
+
|
|
181
|
+
# Download if not found
|
|
182
|
+
extracted_files = downloader.download()
|
|
183
|
+
return extracted_files[0] if extracted_files else None
|
|
184
|
+
|
|
185
|
+
except Exception as e:
|
|
186
|
+
logging.error(f"Error checking or downloading mp4decrypt: {e}")
|
|
187
|
+
return None
|
|
188
|
+
|
|
189
|
+
except Exception as e:
|
|
190
|
+
logging.error(f"Error checking or downloading mp4decrypt: {e}")
|
|
191
|
+
return None
|
StreamingCommunity/Util/os.py
CHANGED
|
@@ -20,11 +20,11 @@ from unidecode import unidecode
|
|
|
20
20
|
from rich.console import Console
|
|
21
21
|
from rich.prompt import Prompt
|
|
22
22
|
from pathvalidate import sanitize_filename, sanitize_filepath
|
|
23
|
-
from dns.resolver import dns
|
|
24
23
|
|
|
25
24
|
|
|
26
25
|
# Internal utilities
|
|
27
26
|
from .ffmpeg_installer import check_ffmpeg
|
|
27
|
+
from .bento4_installer import check_mp4decrypt
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
# Variable
|
|
@@ -284,43 +284,6 @@ class InternManager():
|
|
|
284
284
|
else:
|
|
285
285
|
return f"{bytes / (1024 * 1024):.2f} MB/s"
|
|
286
286
|
|
|
287
|
-
# def check_dns_provider(self):
|
|
288
|
-
# """
|
|
289
|
-
# Check if the system's current DNS server matches any known DNS providers.
|
|
290
|
-
|
|
291
|
-
# Returns:
|
|
292
|
-
# bool: True if the current DNS server matches a known provider,
|
|
293
|
-
# False if no match is found or in case of errors
|
|
294
|
-
# """
|
|
295
|
-
# dns_providers = {
|
|
296
|
-
# "Cloudflare": ["1.1.1.1", "1.0.0.1"],
|
|
297
|
-
# "Google": ["8.8.8.8", "8.8.4.4"],
|
|
298
|
-
# "OpenDNS": ["208.67.222.222", "208.67.220.220"],
|
|
299
|
-
# "Quad9": ["9.9.9.9", "149.112.112.112"],
|
|
300
|
-
# "AdGuard": ["94.140.14.14", "94.140.15.15"],
|
|
301
|
-
# "Comodo": ["8.26.56.26", "8.20.247.20"],
|
|
302
|
-
# "Level3": ["209.244.0.3", "209.244.0.4"],
|
|
303
|
-
# "Norton": ["199.85.126.10", "199.85.127.10"],
|
|
304
|
-
# "CleanBrowsing": ["185.228.168.9", "185.228.169.9"],
|
|
305
|
-
# "Yandex": ["77.88.8.8", "77.88.8.1"]
|
|
306
|
-
# }
|
|
307
|
-
|
|
308
|
-
# try:
|
|
309
|
-
# resolver = dns.resolver.Resolver()
|
|
310
|
-
# nameservers = resolver.nameservers
|
|
311
|
-
|
|
312
|
-
# if not nameservers:
|
|
313
|
-
# return False
|
|
314
|
-
|
|
315
|
-
# for server in nameservers:
|
|
316
|
-
# for provider, ips in dns_providers.items():
|
|
317
|
-
# if server in ips:
|
|
318
|
-
# return True
|
|
319
|
-
# return False
|
|
320
|
-
|
|
321
|
-
# except Exception:
|
|
322
|
-
# return False
|
|
323
|
-
|
|
324
287
|
def check_dns_resolve(self, domains_list: list = None):
|
|
325
288
|
"""
|
|
326
289
|
Check if the system's current DNS server can resolve a domain name.
|
|
@@ -348,6 +311,7 @@ class OsSummary:
|
|
|
348
311
|
self.ffmpeg_path = None
|
|
349
312
|
self.ffprobe_path = None
|
|
350
313
|
self.ffplay_path = None
|
|
314
|
+
self.mp4decrypt_path = None
|
|
351
315
|
|
|
352
316
|
def get_binary_directory(self):
|
|
353
317
|
"""Get the binary directory based on OS."""
|
|
@@ -442,10 +406,8 @@ class OsSummary:
|
|
|
442
406
|
}
|
|
443
407
|
arch = arch_map.get(arch, arch)
|
|
444
408
|
|
|
445
|
-
# Check
|
|
409
|
+
# Check FFmpeg binaries
|
|
446
410
|
if os.path.exists(binary_dir):
|
|
447
|
-
|
|
448
|
-
# Search for any file containing 'ffmpeg' and the architecture
|
|
449
411
|
ffmpeg_files = glob.glob(os.path.join(binary_dir, f'*ffmpeg*{arch}*'))
|
|
450
412
|
ffprobe_files = glob.glob(os.path.join(binary_dir, f'*ffprobe*{arch}*'))
|
|
451
413
|
|
|
@@ -453,7 +415,6 @@ class OsSummary:
|
|
|
453
415
|
self.ffmpeg_path = ffmpeg_files[0]
|
|
454
416
|
self.ffprobe_path = ffprobe_files[0]
|
|
455
417
|
|
|
456
|
-
# Set executable permissions if needed
|
|
457
418
|
if system != 'windows':
|
|
458
419
|
os.chmod(self.ffmpeg_path, 0o755)
|
|
459
420
|
os.chmod(self.ffprobe_path, 0o755)
|
|
@@ -462,11 +423,19 @@ class OsSummary:
|
|
|
462
423
|
else:
|
|
463
424
|
self.ffmpeg_path, self.ffprobe_path, self.ffplay_path = check_ffmpeg()
|
|
464
425
|
|
|
426
|
+
# Check mp4decrypt
|
|
427
|
+
self.mp4decrypt_path = check_mp4decrypt()
|
|
428
|
+
|
|
465
429
|
if not self.ffmpeg_path or not self.ffprobe_path:
|
|
466
430
|
console.log("[red]Can't locate ffmpeg or ffprobe")
|
|
467
431
|
sys.exit(0)
|
|
468
432
|
|
|
433
|
+
if not self.mp4decrypt_path:
|
|
434
|
+
console.log("[yellow]Warning: mp4decrypt not found")
|
|
435
|
+
|
|
469
436
|
console.print(f"[cyan]Path: [red]ffmpeg [bold yellow]'{self.ffmpeg_path}'[/bold yellow][white], [red]ffprobe '[bold yellow]{self.ffprobe_path}'[/bold yellow]")
|
|
437
|
+
if self.mp4decrypt_path:
|
|
438
|
+
console.print(f"[cyan]Path: [red]mp4decrypt [bold yellow]'{self.mp4decrypt_path}'[/bold yellow]")
|
|
470
439
|
|
|
471
440
|
|
|
472
441
|
os_manager = OsManager()
|
|
@@ -479,10 +448,6 @@ def suppress_output():
|
|
|
479
448
|
with contextlib.redirect_stdout(io.StringIO()):
|
|
480
449
|
yield
|
|
481
450
|
|
|
482
|
-
def compute_sha1_hash(input_string: str) -> str:
|
|
483
|
-
"""Computes the SHA-1 hash of the input string."""
|
|
484
|
-
return hashlib.sha1(input_string.encode()).hexdigest()
|
|
485
|
-
|
|
486
451
|
def get_call_stack():
|
|
487
452
|
"""Retrieves the current call stack with details about each call."""
|
|
488
453
|
stack = inspect.stack()
|
|
@@ -514,6 +479,10 @@ def get_ffprobe_path():
|
|
|
514
479
|
"""Returns the path of FFprobe."""
|
|
515
480
|
return os_summary.ffprobe_path
|
|
516
481
|
|
|
482
|
+
def get_mp4decrypt_path():
|
|
483
|
+
"""Returns the path of mp4decrypt."""
|
|
484
|
+
return os_summary.mp4decrypt_path
|
|
485
|
+
|
|
517
486
|
def get_wvd_path():
|
|
518
487
|
"""
|
|
519
488
|
Searches the system's binary folder and returns the path of the first file ending with 'wvd'.
|
StreamingCommunity/__init__.py
CHANGED
|
@@ -3,4 +3,5 @@
|
|
|
3
3
|
from .run import main
|
|
4
4
|
from .Lib.Downloader.HLS.downloader import HLS_Downloader
|
|
5
5
|
from .Lib.Downloader.MP4.downloader import MP4_downloader
|
|
6
|
-
from .Lib.Downloader.TOR.downloader import TOR_downloader
|
|
6
|
+
from .Lib.Downloader.TOR.downloader import TOR_downloader
|
|
7
|
+
from .Lib.Downloader.DASH.downloader import DASH_Downloader
|
StreamingCommunity/run.py
CHANGED
|
@@ -33,6 +33,7 @@ from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance, Teleg
|
|
|
33
33
|
SHOW_TRENDING = config_manager.get_bool('DEFAULT', 'show_trending')
|
|
34
34
|
NOT_CLOSE_CONSOLE = config_manager.get_bool('DEFAULT', 'not_close')
|
|
35
35
|
TELEGRAM_BOT = config_manager.get_bool('DEFAULT', 'telegram_bot')
|
|
36
|
+
BYPASS_DNS = config_manager.get_bool('DEFAULT', 'bypass_dns')
|
|
36
37
|
|
|
37
38
|
|
|
38
39
|
# Variable
|
|
@@ -227,16 +228,16 @@ def main(script_id = 0):
|
|
|
227
228
|
# Get all site hostname
|
|
228
229
|
hostname_list = [hostname for site_info in config_manager.configSite.values() if (hostname := _extract_hostname(site_info.get('full_url')))]
|
|
229
230
|
|
|
230
|
-
if not
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
231
|
+
if not BYPASS_DNS:
|
|
232
|
+
if not internet_manager.check_dns_resolve(hostname_list):
|
|
233
|
+
console.print("[red] ERROR: DNS configuration is required!")
|
|
234
|
+
console.print("[red]The program cannot function correctly without proper DNS settings.")
|
|
235
|
+
console.print("[yellow]Please configure one of these DNS servers:")
|
|
236
|
+
console.print("[red]• Cloudflare (1.1.1.1) 'https://developers.cloudflare.com/1.1.1.1/setup/windows/'")
|
|
237
|
+
console.print("[red]• Quad9 (9.9.9.9) 'https://docs.quad9.net/Setup_Guides/Windows/Windows_10/'")
|
|
238
|
+
console.print("\n[yellow]⚠️ The program will not work until you configure your DNS settings.")
|
|
239
|
+
|
|
240
|
+
os._exit(0)
|
|
240
241
|
|
|
241
242
|
# Load search functions
|
|
242
243
|
search_functions = load_search_functions()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: StreamingCommunity
|
|
3
|
-
Version: 3.2.
|
|
3
|
+
Version: 3.2.8
|
|
4
4
|
Home-page: https://github.com/Lovi-0/StreamingCommunity
|
|
5
5
|
Author: Lovi-0
|
|
6
6
|
Project-URL: Bug Reports, https://github.com/Lovi-0/StreamingCommunity/issues
|
|
@@ -18,7 +18,6 @@ Requires-Dist: certifi
|
|
|
18
18
|
Requires-Dist: psutil
|
|
19
19
|
Requires-Dist: unidecode
|
|
20
20
|
Requires-Dist: curl_cffi
|
|
21
|
-
Requires-Dist: dnspython
|
|
22
21
|
Requires-Dist: jsbeautifier
|
|
23
22
|
Requires-Dist: pathvalidate
|
|
24
23
|
Requires-Dist: pycryptodomex
|
|
@@ -149,7 +148,7 @@ python run_streaming.py
|
|
|
149
148
|
Download HTTP Live Streaming (HLS) content from m3u8 URLs.
|
|
150
149
|
|
|
151
150
|
```python
|
|
152
|
-
from StreamingCommunity
|
|
151
|
+
from StreamingCommunity import HLS_Downloader
|
|
153
152
|
|
|
154
153
|
# Initialize with m3u8 URL and optional output path
|
|
155
154
|
downloader = HLS_Downloader(
|
|
@@ -170,7 +169,7 @@ See [HLS example](./Test/Download/HLS.py) for complete usage.
|
|
|
170
169
|
Direct MP4 file downloader with support for custom headers and referrer.
|
|
171
170
|
|
|
172
171
|
```python
|
|
173
|
-
from StreamingCommunity
|
|
172
|
+
from StreamingCommunity import MP4_downloader
|
|
174
173
|
|
|
175
174
|
# Basic usage
|
|
176
175
|
downloader = MP4_downloader(
|
|
@@ -202,7 +201,7 @@ See [MP4 example](./Test/Download/MP4.py) for complete usage.
|
|
|
202
201
|
Download content via torrent magnet links.
|
|
203
202
|
|
|
204
203
|
```python
|
|
205
|
-
from StreamingCommunity
|
|
204
|
+
from StreamingCommunity import TOR_downloader
|
|
206
205
|
|
|
207
206
|
# Initialize torrent client
|
|
208
207
|
client = TOR_downloader()
|
|
@@ -526,8 +525,6 @@ To enable qBittorrent integration, follow the setup guide [here](https://github.
|
|
|
526
525
|
"default_video_workser": 12,
|
|
527
526
|
"default_audio_workser": 12,
|
|
528
527
|
"segment_timeout": 8,
|
|
529
|
-
"download_audio": true,
|
|
530
|
-
"merge_audio": true,
|
|
531
528
|
"specific_list_audio": [
|
|
532
529
|
"ita"
|
|
533
530
|
],
|
|
@@ -552,7 +549,6 @@ To enable qBittorrent integration, follow the setup guide [here](https://github.
|
|
|
552
549
|
|
|
553
550
|
#### Audio Settings
|
|
554
551
|
- `download_audio`: Whether to download audio tracks
|
|
555
|
-
- `merge_audio`: Whether to merge audio with video
|
|
556
552
|
- `specific_list_audio`: List of audio languages to download
|
|
557
553
|
* Can be changed with `--specific_list_audio ita,eng`
|
|
558
554
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
StreamingCommunity/__init__.py,sha256=
|
|
1
|
+
StreamingCommunity/__init__.py,sha256=NPxefEfOANbfmXVfYMlofaZfzcMMcrUUpjWx81X_cQQ,267
|
|
2
2
|
StreamingCommunity/global_search.py,sha256=ip3D0OKNRTXHpe_Wy7v2KM-yNZdnnbG5FOBYSSk6wB8,12401
|
|
3
|
-
StreamingCommunity/run.py,sha256=
|
|
3
|
+
StreamingCommunity/run.py,sha256=_7e8BEGFCCHdKSv64q6M3IenxT0-TQ629VJaAZMPhhY,14242
|
|
4
4
|
StreamingCommunity/Api/Player/ddl.py,sha256=cPinK99iX4ThvAHLlzcACcnFvM-M_NK0f4imh9PQY1I,2174
|
|
5
5
|
StreamingCommunity/Api/Player/hdplayer.py,sha256=TTI_DNR9swFlUayJPfZBwqcH2pmw-oLk9PHu725wxnY,1936
|
|
6
6
|
StreamingCommunity/Api/Player/maxstream.py,sha256=JlVTCAo9ze0wF2h0eNPYqdorhwK7DPXpmLAyHMnT7-Y,5017
|
|
@@ -12,52 +12,52 @@ StreamingCommunity/Api/Player/vixcloud.py,sha256=0DnukAIBqGqTmL9I6JkpAkHLMf1UG1D
|
|
|
12
12
|
StreamingCommunity/Api/Player/Helper/Vixcloud/js_parser.py,sha256=U-8QlD5kGzIk3-4t4D6QyYmiDe8UBrSuVi1YHRQb7AU,4295
|
|
13
13
|
StreamingCommunity/Api/Player/Helper/Vixcloud/util.py,sha256=mTEAND-KepqRHRYlAorJ1mc6ICB-f0Whhp5OZ8R4MJ8,5306
|
|
14
14
|
StreamingCommunity/Api/Site/altadefinizione/__init__.py,sha256=6CF9MCh3AstetNlTqG_uzRUQEmMR4iix2vPzGbl3EWM,4180
|
|
15
|
-
StreamingCommunity/Api/Site/altadefinizione/film.py,sha256=
|
|
16
|
-
StreamingCommunity/Api/Site/altadefinizione/series.py,sha256
|
|
15
|
+
StreamingCommunity/Api/Site/altadefinizione/film.py,sha256=fMrDew-M9S4ZTXNTYir4GJexQjG5aSlIYL_k-92iWKc,3701
|
|
16
|
+
StreamingCommunity/Api/Site/altadefinizione/series.py,sha256=I_Fol3grdTZmLwLFskkU7v9fcddzQUENtWmgeNXoC4s,8177
|
|
17
17
|
StreamingCommunity/Api/Site/altadefinizione/site.py,sha256=2kUNQ8ebYlX5dkSql-CvEhU01TOTNtuyEMIAD6SC3lg,2865
|
|
18
18
|
StreamingCommunity/Api/Site/altadefinizione/util/ScrapeSerie.py,sha256=9iulNlnNAhTfI5iKNW3I6pZqYeYwovAswa13L3LPGDM,4251
|
|
19
19
|
StreamingCommunity/Api/Site/animeunity/__init__.py,sha256=cLuZOgtQ-1vKIKf3iJjznBu3ET1Q3WZtO0UoK9U0YPU,4034
|
|
20
20
|
StreamingCommunity/Api/Site/animeunity/film.py,sha256=Vqg6yag2siR-Y3ougBsV8mzdQXChxg6ghz_KVXFQ3pE,998
|
|
21
|
-
StreamingCommunity/Api/Site/animeunity/serie.py,sha256=
|
|
21
|
+
StreamingCommunity/Api/Site/animeunity/serie.py,sha256=wqpbry4wkkwc5M2sf3k6icQRRZ7Jw9hv4BE8BlMHec0,5696
|
|
22
22
|
StreamingCommunity/Api/Site/animeunity/site.py,sha256=GLULPQATMHcXiH99d772v1ICH-PnnZgSM3q5__eN-gs,4977
|
|
23
23
|
StreamingCommunity/Api/Site/animeunity/util/ScrapeSerie.py,sha256=UladSvOlTEVLiV0-rAz45zrET5qRHMuTGuKEpeQoumU,3872
|
|
24
24
|
StreamingCommunity/Api/Site/animeworld/__init__.py,sha256=fjStJyOl6VBVDgoi6wr2yA0CQ_UQ4atTBzal0gOBgRM,2822
|
|
25
|
-
StreamingCommunity/Api/Site/animeworld/film.py,sha256=
|
|
26
|
-
StreamingCommunity/Api/Site/animeworld/serie.py,sha256=
|
|
25
|
+
StreamingCommunity/Api/Site/animeworld/film.py,sha256=Ysp0k5AlrOsl19S9LV4nwVg8cjFf5w0FZRO9CiO6NxA,1748
|
|
26
|
+
StreamingCommunity/Api/Site/animeworld/serie.py,sha256=b1yuBnLNqJ-IWEVqLnQuYv6VbUQ60a5YFpZbJrS3lnI,3486
|
|
27
27
|
StreamingCommunity/Api/Site/animeworld/site.py,sha256=HBUAYiOa-UPGAO4lyTL1qIqqpDNVhWRHZ-nyLFltl7I,3702
|
|
28
28
|
StreamingCommunity/Api/Site/animeworld/util/ScrapeSerie.py,sha256=EDTouftxigb4ojTEGWC0sOgOLCNjE1-1GFEMrK-qzRQ,3615
|
|
29
29
|
StreamingCommunity/Api/Site/cb01new/__init__.py,sha256=95M3DiNbLbZ6v1oFkPuAPEVJWf12W2JzJvxZKjZs_V8,2071
|
|
30
|
-
StreamingCommunity/Api/Site/cb01new/film.py,sha256=
|
|
30
|
+
StreamingCommunity/Api/Site/cb01new/film.py,sha256=mjJQFoh8aTp7ydmr6_WLT0G0_HfEDGeVXp3QfSalVRw,1680
|
|
31
31
|
StreamingCommunity/Api/Site/cb01new/site.py,sha256=82GPxjOyY7Dlj1WbA0YNovgbKhuF3Vmca07IVXGh6lE,2139
|
|
32
32
|
StreamingCommunity/Api/Site/crunchyroll/__init__.py,sha256=hBb29hfYD_rGMkhhAknnkBOB-oG_yE2rfUtbPw0wPLQ,3456
|
|
33
|
-
StreamingCommunity/Api/Site/crunchyroll/film.py,sha256=
|
|
34
|
-
StreamingCommunity/Api/Site/crunchyroll/series.py,sha256=
|
|
33
|
+
StreamingCommunity/Api/Site/crunchyroll/film.py,sha256=AkDWcvDe43zSJH_Pxig4JmagDJuUw2PkB_q6dChL7MQ,2559
|
|
34
|
+
StreamingCommunity/Api/Site/crunchyroll/series.py,sha256=VCBnVrOj_Cmu4pAWGSfAgf-7GP8GsmSINLfHBwZ7f6U,7209
|
|
35
35
|
StreamingCommunity/Api/Site/crunchyroll/site.py,sha256=BmOQw060M7KvH_wL-V_x1s6918rxM_Pp54tuNgG5ju0,3210
|
|
36
|
-
StreamingCommunity/Api/Site/crunchyroll/util/ScrapeSerie.py,sha256=
|
|
36
|
+
StreamingCommunity/Api/Site/crunchyroll/util/ScrapeSerie.py,sha256=ZY6z4pT5q7igiNZnJAvE9x0WiORTvFSH-U_CpqOzusA,7855
|
|
37
37
|
StreamingCommunity/Api/Site/crunchyroll/util/get_license.py,sha256=KpVvJbGUTLeVD-tt8r7ajBPWVT7Tm6GrKwzpW8CS-tg,6881
|
|
38
38
|
StreamingCommunity/Api/Site/guardaserie/__init__.py,sha256=vnbt1DVG6nmHaLSUOO_2NQYi9iTiOPLrwtvUd_DZDZg,2800
|
|
39
|
-
StreamingCommunity/Api/Site/guardaserie/series.py,sha256=
|
|
39
|
+
StreamingCommunity/Api/Site/guardaserie/series.py,sha256=o7jjf64E95A2rGzYSEARTsZgOlQHeuXtfp4IlD4GtTU,6462
|
|
40
40
|
StreamingCommunity/Api/Site/guardaserie/site.py,sha256=z9PKJesarOFlIrCeaed5095poJWYroVoWRV1LYTR4E4,2252
|
|
41
41
|
StreamingCommunity/Api/Site/guardaserie/util/ScrapeSerie.py,sha256=hPul0-9sgi0IZplHn9UywtpAa3xhVKDC0lefb5l81-g,4413
|
|
42
42
|
StreamingCommunity/Api/Site/mediasetinfinity/__init__.py,sha256=dBKs42xEuIjHZ8mnqmjpdySjFYYuwDi6drWbBvzMzR8,3257
|
|
43
|
-
StreamingCommunity/Api/Site/mediasetinfinity/film.py,sha256=
|
|
44
|
-
StreamingCommunity/Api/Site/mediasetinfinity/series.py,sha256=
|
|
43
|
+
StreamingCommunity/Api/Site/mediasetinfinity/film.py,sha256=mOKktBmlW90mRDZfENWNpp5l2svRGXeo6MG0S7X2nlM,2582
|
|
44
|
+
StreamingCommunity/Api/Site/mediasetinfinity/series.py,sha256=JLcXcq5OKqBCYwcuworzHl2DNXO2ivxV-cqF8HaqKD8,7131
|
|
45
45
|
StreamingCommunity/Api/Site/mediasetinfinity/site.py,sha256=SVNcqcQAOxAKw0mcUzeQqDbfcnRFEPtxKNjl2Xe7FlY,3240
|
|
46
46
|
StreamingCommunity/Api/Site/mediasetinfinity/util/ScrapeSerie.py,sha256=-PUhtJ1Umb1SjLh6Ujs0cOmOi-uC0WrSkIecv6XDhgQ,9382
|
|
47
47
|
StreamingCommunity/Api/Site/mediasetinfinity/util/fix_mpd.py,sha256=B7uZfQ8X4p8KsiPVangFSs5rKKKpA3tavjPCdNrqyCc,1712
|
|
48
|
-
StreamingCommunity/Api/Site/mediasetinfinity/util/get_license.py,sha256
|
|
48
|
+
StreamingCommunity/Api/Site/mediasetinfinity/util/get_license.py,sha256=-uM5G2M-9MwJq-TyXEV6PcpsWBoGdJ8KcuNQwgn5cos,6330
|
|
49
49
|
StreamingCommunity/Api/Site/raiplay/__init__.py,sha256=6Hjkc_C0du_stc9cOKJIyWjW-YQPMmJLoLXZpiwX1S8,3106
|
|
50
|
-
StreamingCommunity/Api/Site/raiplay/film.py,sha256=
|
|
51
|
-
StreamingCommunity/Api/Site/raiplay/series.py,sha256=
|
|
50
|
+
StreamingCommunity/Api/Site/raiplay/film.py,sha256=uGN4sMMSkUJHjOUZbI-8yjpy5oGTcw1sNTPxct_PKvc,1967
|
|
51
|
+
StreamingCommunity/Api/Site/raiplay/series.py,sha256=Lfxe0cvsipcDZbX6W2bYLbnuXb-pcEEgBT-Tq8CXwaM,6147
|
|
52
52
|
StreamingCommunity/Api/Site/raiplay/site.py,sha256=kWo2YPcUOPgsThJU_RahnDwJP4QpkmgzdzRqtoubR5U,3166
|
|
53
53
|
StreamingCommunity/Api/Site/raiplay/util/ScrapeSerie.py,sha256=V7fFP9KLuMXitRsHtInxUJBcGClfSk_tOUNWFC8pG5A,5807
|
|
54
54
|
StreamingCommunity/Api/Site/streamingcommunity/__init__.py,sha256=q5F3e2h7fuYKGLMfXOzK71sGfPW38CYP-dfGjwFe3mQ,5577
|
|
55
|
-
StreamingCommunity/Api/Site/streamingcommunity/film.py,sha256=
|
|
56
|
-
StreamingCommunity/Api/Site/streamingcommunity/series.py,sha256=
|
|
55
|
+
StreamingCommunity/Api/Site/streamingcommunity/film.py,sha256=ma9cLfU4w_e-qoN2JMLZdB4_LZoYa38W79y_MYstwTg,2723
|
|
56
|
+
StreamingCommunity/Api/Site/streamingcommunity/series.py,sha256=TlqvvOdB1FCHwsGCfvcBE6bzcJbOEfPC9lGiMrDm5vU,8952
|
|
57
57
|
StreamingCommunity/Api/Site/streamingcommunity/site.py,sha256=MMi4mcKu0iPhud685IVW4xc7hFkJe09OjT6L90tsRHk,3985
|
|
58
58
|
StreamingCommunity/Api/Site/streamingcommunity/util/ScrapeSerie.py,sha256=vnqVwDb4sxEXzMcr9B4ZZHFuADwcHSMCa3VMguKIe_U,5555
|
|
59
59
|
StreamingCommunity/Api/Site/streamingwatch/__init__.py,sha256=Swp2KHYBH96W8yBbjGF5x-xjnoal7hNj1JE05CWMsz4,3337
|
|
60
|
-
StreamingCommunity/Api/Site/streamingwatch/film.py,sha256=
|
|
60
|
+
StreamingCommunity/Api/Site/streamingwatch/film.py,sha256=bLV3KjF7KFhpp8BvfQrpSFP9R__YmTlB-ypJBSivT5o,1637
|
|
61
61
|
StreamingCommunity/Api/Site/streamingwatch/series.py,sha256=ak4RdpR2-IuAimP3x5ZqEv9CH2_RcTZGN1hXlpoixJo,6141
|
|
62
62
|
StreamingCommunity/Api/Site/streamingwatch/site.py,sha256=dHEL5_3nSBynlXz82IUbCHkxIpuvhmE2aRpdE1b6wq8,3448
|
|
63
63
|
StreamingCommunity/Api/Site/streamingwatch/util/ScrapeSerie.py,sha256=Ui_2Vccf6C_ZLLMxLbUL0r5n8mWQiQTl4YZQAhXRf0g,4268
|
|
@@ -70,11 +70,11 @@ StreamingCommunity/Api/Template/Util/manage_ep.py,sha256=FYe2DC9SXIXzlRYI7fW4ieB
|
|
|
70
70
|
StreamingCommunity/Lib/Downloader/__init__.py,sha256=JhbBh5hOnSM7VmtkxJ7zZ_FtWEC1JdnKThsSBjLV5FY,140
|
|
71
71
|
StreamingCommunity/Lib/Downloader/DASH/cdm_helpher.py,sha256=at7_pYAbb_391PrQXWIxPZYT9gaS7qrVgKMdbQSMSyw,4714
|
|
72
72
|
StreamingCommunity/Lib/Downloader/DASH/decrypt.py,sha256=RuzxsXjJKKzdbbUESfujCXqg_t1brOJLAvVNFWej48o,2353
|
|
73
|
-
StreamingCommunity/Lib/Downloader/DASH/downloader.py,sha256=
|
|
74
|
-
StreamingCommunity/Lib/Downloader/DASH/parser.py,sha256=
|
|
73
|
+
StreamingCommunity/Lib/Downloader/DASH/downloader.py,sha256=nuYZLM_Np0TKZ7wc7hYL5hivrEzqQ7sdvfx40LnVP_Q,8093
|
|
74
|
+
StreamingCommunity/Lib/Downloader/DASH/parser.py,sha256=ZW6oErH9i8Nrp6yPc8usiRBv9ftkfVYh46wEg8MOl6o,9835
|
|
75
75
|
StreamingCommunity/Lib/Downloader/DASH/segments.py,sha256=ZV9FYibbS8E722MHVxl16N6rN1tPioZTNqO4jWBpGGo,12672
|
|
76
|
-
StreamingCommunity/Lib/Downloader/HLS/downloader.py,sha256=
|
|
77
|
-
StreamingCommunity/Lib/Downloader/HLS/segments.py,sha256=
|
|
76
|
+
StreamingCommunity/Lib/Downloader/HLS/downloader.py,sha256=yzusDF32uSR_MZqdrNoJ27nR2VXRvflckTxiw04JoNk,21189
|
|
77
|
+
StreamingCommunity/Lib/Downloader/HLS/segments.py,sha256=8Ze3s2YNglBonXKngDIs89LH48b_IZy7vx4h138uydQ,17982
|
|
78
78
|
StreamingCommunity/Lib/Downloader/MP4/downloader.py,sha256=OBObY930wrOG0IUlDRROOfgU_u6uYHvckED4nnPjXzs,7367
|
|
79
79
|
StreamingCommunity/Lib/Downloader/TOR/downloader.py,sha256=CrRGdLGI_45AnhtTZm8r7KO7uGmU9k6pywy-qO18LG8,19242
|
|
80
80
|
StreamingCommunity/Lib/FFmpeg/__init__.py,sha256=6PBsZdE1jrD2EKOVyx3JEHnyDZzVeKlPkH5T0zyfOgU,130
|
|
@@ -90,21 +90,22 @@ StreamingCommunity/Lib/TMBD/__init__.py,sha256=XzE42tw3Ws59DD1PF8WmGtZ0D4D7Hk3Af
|
|
|
90
90
|
StreamingCommunity/Lib/TMBD/obj_tmbd.py,sha256=dRSvJFS5yqmsBZcw2wqbStcBtXNjU_3n5czMyremAtU,1187
|
|
91
91
|
StreamingCommunity/Lib/TMBD/tmdb.py,sha256=byg0EFnlmd9JeLvn1N9K3QkB1KEfeMuFa7OVfGqks1Y,10685
|
|
92
92
|
StreamingCommunity/TelegramHelp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
93
|
-
StreamingCommunity/TelegramHelp/config.json,sha256=
|
|
93
|
+
StreamingCommunity/TelegramHelp/config.json,sha256=4Tnram-K5wNK0QjWY9R4VpiHfGnMbahvDEdJ2VBWOoc,1460
|
|
94
94
|
StreamingCommunity/TelegramHelp/telegram_bot.py,sha256=zCqj7xBofh9FYfEYl55mgT945jqtKo7qJhn-SMLvAvA,26455
|
|
95
95
|
StreamingCommunity/Upload/update.py,sha256=ZGQHcnTLAfXla_PqvykDeg2-WKOYfX9zX2I3KrdKHpc,3814
|
|
96
|
-
StreamingCommunity/Upload/version.py,sha256=
|
|
96
|
+
StreamingCommunity/Upload/version.py,sha256=NaOdgJwSHkakkbsYisKWKKqEMAjCYxhIHttZMn77p_c,171
|
|
97
|
+
StreamingCommunity/Util/bento4_installer.py,sha256=P5ipziMCvezxan8GUh9vm8B1LXGyHusFVDf842LSwis,6966
|
|
97
98
|
StreamingCommunity/Util/color.py,sha256=NvD0Eni-25oOOkY-szCEoc0lGvzQxyL7xhM0RE4EvUM,458
|
|
98
|
-
StreamingCommunity/Util/config_json.py,sha256=
|
|
99
|
+
StreamingCommunity/Util/config_json.py,sha256=4sn-vvrYybZMOlT-blx3bM9njxQRQS_HwSPfqQ0qZ94,24226
|
|
99
100
|
StreamingCommunity/Util/ffmpeg_installer.py,sha256=yRVIPwbh05tZ-duZmXkH0qasLNxaQCAT_E4cTP79Z3c,14890
|
|
100
|
-
StreamingCommunity/Util/headers.py,sha256=
|
|
101
|
+
StreamingCommunity/Util/headers.py,sha256=RP3A6Gr8UB8VU6uzw_yDOjEKkIFKpi7Gi6_w2ACxE30,292
|
|
101
102
|
StreamingCommunity/Util/logger.py,sha256=9kGD6GmWj2pM8ADpJc85o7jm8DD0c5Aguqnq-9kmxos,3314
|
|
102
103
|
StreamingCommunity/Util/message.py,sha256=81vPmsGBusovIhheIO4Ec6p7BYvMj1wE_CthtRyp6OM,1333
|
|
103
|
-
StreamingCommunity/Util/os.py,sha256=
|
|
104
|
+
StreamingCommunity/Util/os.py,sha256=vLNRGWsQYTSUGdpj19fR_n0i-6bhZYeJh5IZpahdyKM,16832
|
|
104
105
|
StreamingCommunity/Util/table.py,sha256=Nw5PlsvfEIOQZWy5VhsU5OK3heuBXGwsqmLl0k8yQzc,9813
|
|
105
|
-
streamingcommunity-3.2.
|
|
106
|
-
streamingcommunity-3.2.
|
|
107
|
-
streamingcommunity-3.2.
|
|
108
|
-
streamingcommunity-3.2.
|
|
109
|
-
streamingcommunity-3.2.
|
|
110
|
-
streamingcommunity-3.2.
|
|
106
|
+
streamingcommunity-3.2.8.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
107
|
+
streamingcommunity-3.2.8.dist-info/METADATA,sha256=9f38qTwHxcDyf-v7jtyZOL7orWpp5x9IZkRogepZAwU,25312
|
|
108
|
+
streamingcommunity-3.2.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
109
|
+
streamingcommunity-3.2.8.dist-info/entry_points.txt,sha256=Qph9XYfDC8n4LfDLOSl6gJGlkb9eFb5f-JOr_Wb_5rk,67
|
|
110
|
+
streamingcommunity-3.2.8.dist-info/top_level.txt,sha256=YsOcxKP-WOhWpIWgBlh0coll9XUx7aqmRPT7kmt3fH0,19
|
|
111
|
+
streamingcommunity-3.2.8.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|