StreamingCommunity 3.3.3__py3-none-any.whl → 3.3.6__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/__init__.py +17 -18
- StreamingCommunity/Api/Site/altadefinizione/series.py +4 -0
- StreamingCommunity/Api/Site/animeunity/__init__.py +14 -15
- StreamingCommunity/Api/Site/animeunity/serie.py +1 -1
- StreamingCommunity/Api/Site/animeworld/__init__.py +15 -13
- StreamingCommunity/Api/Site/animeworld/serie.py +1 -1
- StreamingCommunity/Api/Site/crunchyroll/__init__.py +16 -17
- StreamingCommunity/Api/Site/crunchyroll/series.py +6 -1
- StreamingCommunity/Api/Site/guardaserie/__init__.py +17 -19
- StreamingCommunity/Api/Site/guardaserie/series.py +4 -0
- StreamingCommunity/Api/Site/guardaserie/site.py +2 -7
- StreamingCommunity/Api/Site/mediasetinfinity/__init__.py +15 -15
- StreamingCommunity/Api/Site/mediasetinfinity/series.py +4 -0
- StreamingCommunity/Api/Site/mediasetinfinity/site.py +12 -2
- StreamingCommunity/Api/Site/mediasetinfinity/util/ScrapeSerie.py +67 -98
- StreamingCommunity/Api/Site/raiplay/__init__.py +15 -15
- StreamingCommunity/Api/Site/raiplay/series.py +5 -1
- StreamingCommunity/Api/Site/streamingcommunity/__init__.py +16 -14
- StreamingCommunity/Api/Site/streamingwatch/__init__.py +12 -12
- StreamingCommunity/Api/Site/streamingwatch/series.py +4 -0
- StreamingCommunity/Api/Template/Class/SearchType.py +0 -1
- StreamingCommunity/Api/Template/Util/manage_ep.py +1 -11
- StreamingCommunity/Api/Template/site.py +2 -3
- StreamingCommunity/Lib/Downloader/DASH/decrypt.py +4 -1
- StreamingCommunity/Lib/Downloader/DASH/downloader.py +55 -17
- StreamingCommunity/Lib/Downloader/DASH/segments.py +73 -17
- StreamingCommunity/Lib/Downloader/HLS/downloader.py +282 -152
- StreamingCommunity/Lib/Downloader/HLS/segments.py +1 -5
- StreamingCommunity/Lib/FFmpeg/capture.py +1 -1
- StreamingCommunity/Lib/FFmpeg/command.py +6 -6
- StreamingCommunity/Lib/FFmpeg/util.py +11 -30
- StreamingCommunity/Lib/M3U8/estimator.py +27 -13
- StreamingCommunity/Upload/update.py +2 -2
- StreamingCommunity/Upload/version.py +1 -1
- StreamingCommunity/Util/installer/__init__.py +11 -0
- StreamingCommunity/Util/installer/device_install.py +1 -1
- StreamingCommunity/Util/os.py +2 -6
- StreamingCommunity/Util/table.py +40 -8
- StreamingCommunity/run.py +15 -8
- {streamingcommunity-3.3.3.dist-info → streamingcommunity-3.3.6.dist-info}/METADATA +38 -51
- {streamingcommunity-3.3.3.dist-info → streamingcommunity-3.3.6.dist-info}/RECORD +45 -44
- {streamingcommunity-3.3.3.dist-info → streamingcommunity-3.3.6.dist-info}/WHEEL +0 -0
- {streamingcommunity-3.3.3.dist-info → streamingcommunity-3.3.6.dist-info}/entry_points.txt +0 -0
- {streamingcommunity-3.3.3.dist-info → streamingcommunity-3.3.6.dist-info}/licenses/LICENSE +0 -0
- {streamingcommunity-3.3.3.dist-info → streamingcommunity-3.3.6.dist-info}/top_level.txt +0 -0
|
@@ -164,13 +164,13 @@ def join_video(video_path: str, out_path: str, codec: M3U8_Codec = None):
|
|
|
164
164
|
else:
|
|
165
165
|
|
|
166
166
|
if get_use_large_bar():
|
|
167
|
-
capture_ffmpeg_real_time(ffmpeg_cmd, "[cyan]Join video")
|
|
167
|
+
capture_ffmpeg_real_time(ffmpeg_cmd, "[yellow][FFMPEG] [cyan]Join video")
|
|
168
168
|
print()
|
|
169
169
|
|
|
170
170
|
else:
|
|
171
171
|
console.log("[purple]FFmpeg [white][[cyan]Join video[white]] ...")
|
|
172
172
|
with suppress_output():
|
|
173
|
-
capture_ffmpeg_real_time(ffmpeg_cmd, "[cyan]Join video")
|
|
173
|
+
capture_ffmpeg_real_time(ffmpeg_cmd, "[yellow][FFMPEG] [cyan]Join video")
|
|
174
174
|
print()
|
|
175
175
|
|
|
176
176
|
return out_path
|
|
@@ -299,13 +299,13 @@ def join_audios(video_path: str, audio_tracks: List[Dict[str, str]], out_path: s
|
|
|
299
299
|
|
|
300
300
|
else:
|
|
301
301
|
if get_use_large_bar():
|
|
302
|
-
capture_ffmpeg_real_time(ffmpeg_cmd, "[cyan]Join audio")
|
|
302
|
+
capture_ffmpeg_real_time(ffmpeg_cmd, "[yellow][FFMPEG] [cyan]Join audio")
|
|
303
303
|
print()
|
|
304
304
|
|
|
305
305
|
else:
|
|
306
306
|
console.log("[purple]FFmpeg [white][[cyan]Join audio[white]] ...")
|
|
307
307
|
with suppress_output():
|
|
308
|
-
capture_ffmpeg_real_time(ffmpeg_cmd, "[cyan]Join audio")
|
|
308
|
+
capture_ffmpeg_real_time(ffmpeg_cmd, "[yellow][FFMPEG] [cyan]Join audio")
|
|
309
309
|
print()
|
|
310
310
|
|
|
311
311
|
return out_path, use_shortest
|
|
@@ -366,13 +366,13 @@ def join_subtitle(video_path: str, subtitles_list: List[Dict[str, str]], out_pat
|
|
|
366
366
|
|
|
367
367
|
else:
|
|
368
368
|
if get_use_large_bar():
|
|
369
|
-
capture_ffmpeg_real_time(ffmpeg_cmd, "[cyan]Join subtitle")
|
|
369
|
+
capture_ffmpeg_real_time(ffmpeg_cmd, "[yellow][FFMPEG] [cyan]Join subtitle")
|
|
370
370
|
print()
|
|
371
371
|
|
|
372
372
|
else:
|
|
373
373
|
console.log("[purple]FFmpeg [white][[cyan]Join subtitle[white]] ...")
|
|
374
374
|
with suppress_output():
|
|
375
|
-
capture_ffmpeg_real_time(ffmpeg_cmd, "[cyan]Join subtitle")
|
|
375
|
+
capture_ffmpeg_real_time(ffmpeg_cmd, "[yellow][FFMPEG] [cyan]Join subtitle")
|
|
376
376
|
print()
|
|
377
377
|
|
|
378
378
|
return out_path
|
|
@@ -133,8 +133,10 @@ def print_duration_table(file_path: str, description: str = "Duration", return_s
|
|
|
133
133
|
def get_ffprobe_info(file_path):
|
|
134
134
|
"""
|
|
135
135
|
Get format and codec information for a media file using ffprobe.
|
|
136
|
+
|
|
136
137
|
Parameters:
|
|
137
138
|
- file_path (str): Path to the media file.
|
|
139
|
+
|
|
138
140
|
Returns:
|
|
139
141
|
dict: A dictionary containing the format name and a list of codec names.
|
|
140
142
|
Returns None if file does not exist or ffprobe crashes.
|
|
@@ -143,25 +145,8 @@ def get_ffprobe_info(file_path):
|
|
|
143
145
|
logging.error(f"File not found: {file_path}")
|
|
144
146
|
return None
|
|
145
147
|
|
|
146
|
-
# Get ffprobe path and verify it exists
|
|
147
|
-
ffprobe_path = get_ffprobe_path()
|
|
148
|
-
if not ffprobe_path or not os.path.exists(ffprobe_path):
|
|
149
|
-
logging.error(f"FFprobe not found at path: {ffprobe_path}")
|
|
150
|
-
return None
|
|
151
|
-
|
|
152
|
-
# Verify file permissions
|
|
153
|
-
try:
|
|
154
|
-
file_stat = os.stat(file_path)
|
|
155
|
-
logging.info(f"File permissions: {oct(file_stat.st_mode)}")
|
|
156
|
-
if not os.access(file_path, os.R_OK):
|
|
157
|
-
logging.error(f"No read permission for file: {file_path}")
|
|
158
|
-
return None
|
|
159
|
-
except OSError as e:
|
|
160
|
-
logging.error(f"Cannot access file {file_path}: {e}")
|
|
161
|
-
return None
|
|
162
|
-
|
|
163
148
|
try:
|
|
164
|
-
cmd = [
|
|
149
|
+
cmd = [get_ffprobe_path(), '-v', 'error', '-show_format', '-show_streams', '-print_format', 'json', file_path]
|
|
165
150
|
logging.info(f"Running FFprobe command: {' '.join(cmd)}")
|
|
166
151
|
|
|
167
152
|
# Use subprocess.run instead of Popen for better error handling
|
|
@@ -177,20 +162,15 @@ def get_ffprobe_info(file_path):
|
|
|
177
162
|
logging.error(f"FFprobe stderr: {result.stderr}")
|
|
178
163
|
logging.error(f"FFprobe stdout: {result.stdout}")
|
|
179
164
|
logging.error(f"Command: {' '.join(cmd)}")
|
|
180
|
-
logging.error(f"FFprobe path permissions: {oct(os.stat(ffprobe_path).st_mode)}")
|
|
181
165
|
return None
|
|
182
166
|
|
|
183
167
|
# Parse JSON output
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
except json.JSONDecodeError as e:
|
|
191
|
-
logging.error(f"Failed to parse FFprobe output: {e}")
|
|
192
|
-
return None
|
|
193
|
-
|
|
168
|
+
info = json.loads(result.stdout)
|
|
169
|
+
return {
|
|
170
|
+
'format_name': info.get('format', {}).get('format_name'),
|
|
171
|
+
'codec_names': [stream.get('codec_name') for stream in info.get('streams', [])]
|
|
172
|
+
}
|
|
173
|
+
|
|
194
174
|
except Exception as e:
|
|
195
175
|
logging.error(f"FFprobe execution failed: {e}")
|
|
196
176
|
return None
|
|
@@ -223,11 +203,12 @@ def need_to_force_to_ts(file_path):
|
|
|
223
203
|
Parameters:
|
|
224
204
|
- file_path (str): Path to the input media file.
|
|
225
205
|
"""
|
|
226
|
-
logging.info(f"Processing file: {file_path}")
|
|
227
206
|
file_info = get_ffprobe_info(file_path)
|
|
228
207
|
|
|
229
208
|
if is_png_format_or_codec(file_info):
|
|
209
|
+
console.print(f"[yellow]Warning: The input file [green]{os.path.basename(file_path)}[/green] is in PNG format or contains a PNG codec. It will be converted to TS format for processing.[/yellow]")
|
|
230
210
|
return True
|
|
211
|
+
|
|
231
212
|
return False
|
|
232
213
|
|
|
233
214
|
|
|
@@ -30,6 +30,7 @@ class M3U8_Ts_Estimator:
|
|
|
30
30
|
self.lock = threading.Lock()
|
|
31
31
|
self.speed = {"upload": "N/A", "download": "N/A"}
|
|
32
32
|
self._running = True
|
|
33
|
+
self.downloaded_segments_count = 0
|
|
33
34
|
self.speed_thread = threading.Thread(target=self.capture_speed)
|
|
34
35
|
self.speed_thread.daemon = True
|
|
35
36
|
self.speed_thread.start()
|
|
@@ -44,7 +45,8 @@ class M3U8_Ts_Estimator:
|
|
|
44
45
|
logging.error(f"Invalid input values: size={size}")
|
|
45
46
|
return
|
|
46
47
|
|
|
47
|
-
self.
|
|
48
|
+
with self.lock:
|
|
49
|
+
self.ts_file_sizes.append(size)
|
|
48
50
|
|
|
49
51
|
def capture_speed(self, interval: float = 3.0):
|
|
50
52
|
"""Capture the internet speed periodically."""
|
|
@@ -103,27 +105,37 @@ class M3U8_Ts_Estimator:
|
|
|
103
105
|
|
|
104
106
|
def calculate_total_size(self) -> str:
|
|
105
107
|
"""
|
|
106
|
-
Calculate the total size of
|
|
108
|
+
Calculate the estimated total size of all segments.
|
|
107
109
|
|
|
108
110
|
Returns:
|
|
109
|
-
str: The
|
|
111
|
+
str: The estimated total size in a human-readable format.
|
|
110
112
|
"""
|
|
111
113
|
try:
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
114
|
+
with self.lock:
|
|
115
|
+
if not self.ts_file_sizes:
|
|
116
|
+
return "0 B"
|
|
117
|
+
|
|
118
|
+
mean_segment_size = sum(self.ts_file_sizes) / len(self.ts_file_sizes)
|
|
119
|
+
estimated_total_size = mean_segment_size * self.total_segments
|
|
120
|
+
return internet_manager.format_file_size(estimated_total_size)
|
|
118
121
|
|
|
119
122
|
except Exception as e:
|
|
120
123
|
logging.error("An unexpected error occurred: %s", e)
|
|
121
124
|
return "Error"
|
|
122
125
|
|
|
123
|
-
def update_progress_bar(self,
|
|
124
|
-
"""
|
|
126
|
+
def update_progress_bar(self, segment_size: int, progress_counter: tqdm) -> None:
|
|
127
|
+
"""
|
|
128
|
+
Update progress bar with segment information.
|
|
129
|
+
|
|
130
|
+
Parameters:
|
|
131
|
+
- segment_size (int): Size in bytes of the current downloaded segment
|
|
132
|
+
- progress_counter (tqdm): Progress bar instance to update
|
|
133
|
+
"""
|
|
125
134
|
try:
|
|
126
|
-
self.add_ts_file(
|
|
135
|
+
self.add_ts_file(segment_size)
|
|
136
|
+
|
|
137
|
+
with self.lock:
|
|
138
|
+
self.downloaded_segments_count += 1
|
|
127
139
|
|
|
128
140
|
file_total_size = self.calculate_total_size()
|
|
129
141
|
if file_total_size == "Error":
|
|
@@ -151,4 +163,6 @@ class M3U8_Ts_Estimator:
|
|
|
151
163
|
|
|
152
164
|
def stop(self):
|
|
153
165
|
"""Stop speed monitoring thread."""
|
|
154
|
-
self._running = False
|
|
166
|
+
self._running = False
|
|
167
|
+
if self.speed_thread.is_alive():
|
|
168
|
+
self.speed_thread.join(timeout=5.0)
|
|
@@ -6,6 +6,7 @@ import time
|
|
|
6
6
|
import asyncio
|
|
7
7
|
import importlib.metadata
|
|
8
8
|
|
|
9
|
+
|
|
9
10
|
# External library
|
|
10
11
|
import httpx
|
|
11
12
|
from rich.console import Console
|
|
@@ -79,7 +80,6 @@ def update():
|
|
|
79
80
|
try:
|
|
80
81
|
current_version = importlib.metadata.version(__title__)
|
|
81
82
|
except importlib.metadata.PackageNotFoundError:
|
|
82
|
-
#console.print(f"[yellow]Warning: Could not determine installed version for '{__title__}' via importlib.metadata. Falling back to source version.[/yellow]")
|
|
83
83
|
current_version = source_code_version
|
|
84
84
|
|
|
85
85
|
# Get commit details
|
|
@@ -98,4 +98,4 @@ def update():
|
|
|
98
98
|
console.print(f"\n[red]{__title__} has been downloaded [yellow]{total_download_count} [red]times, but only [yellow]{percentual_stars}% [red]of users have starred it.\n\
|
|
99
99
|
[cyan]Help the repository grow today by leaving a [yellow]star [cyan]and [yellow]sharing [cyan]it with others online!")
|
|
100
100
|
|
|
101
|
-
time.sleep(2
|
|
101
|
+
time.sleep(2)
|
StreamingCommunity/Util/os.py
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
import io
|
|
4
4
|
import os
|
|
5
|
-
import time
|
|
6
5
|
import shutil
|
|
7
6
|
import logging
|
|
8
7
|
import socket
|
|
@@ -19,9 +18,7 @@ from pathvalidate import sanitize_filename, sanitize_filepath
|
|
|
19
18
|
|
|
20
19
|
|
|
21
20
|
# Internal utilities
|
|
22
|
-
from .installer
|
|
23
|
-
from .installer.bento4_install import check_mp4decrypt
|
|
24
|
-
from .installer.device_install import check_wvd_path
|
|
21
|
+
from .installer import check_ffmpeg, check_mp4decrypt, check_device_wvd_path
|
|
25
22
|
|
|
26
23
|
|
|
27
24
|
# Variable
|
|
@@ -318,10 +315,9 @@ class OsSummary:
|
|
|
318
315
|
# Check for binaries
|
|
319
316
|
self.ffmpeg_path, self.ffprobe_path, _ = check_ffmpeg()
|
|
320
317
|
self.mp4decrypt_path = check_mp4decrypt()
|
|
321
|
-
self.wvd_path =
|
|
318
|
+
self.wvd_path = check_device_wvd_path()
|
|
322
319
|
|
|
323
320
|
self._display_binary_paths()
|
|
324
|
-
time.sleep(0.3)
|
|
325
321
|
|
|
326
322
|
def _display_binary_paths(self):
|
|
327
323
|
"""Display the paths of all detected binaries."""
|
StreamingCommunity/Util/table.py
CHANGED
|
@@ -29,7 +29,9 @@ TELEGRAM_BOT = config_manager.get_bool('DEFAULT', 'telegram_bot')
|
|
|
29
29
|
|
|
30
30
|
class TVShowManager:
|
|
31
31
|
def __init__(self):
|
|
32
|
-
"""
|
|
32
|
+
"""
|
|
33
|
+
Initialize TVShowManager with default values.
|
|
34
|
+
"""
|
|
33
35
|
self.console = Console()
|
|
34
36
|
self.tv_shows: List[Dict[str, Any]] = []
|
|
35
37
|
self.slice_start = 0
|
|
@@ -53,7 +55,8 @@ class TVShowManager:
|
|
|
53
55
|
Parameters:
|
|
54
56
|
- tv_show (Dict[str, Any]): Dictionary containing TV show details.
|
|
55
57
|
"""
|
|
56
|
-
|
|
58
|
+
if tv_show:
|
|
59
|
+
self.tv_shows.append(tv_show)
|
|
57
60
|
|
|
58
61
|
def display_data(self, data_slice: List[Dict[str, Any]]) -> None:
|
|
59
62
|
"""
|
|
@@ -62,6 +65,14 @@ class TVShowManager:
|
|
|
62
65
|
Parameters:
|
|
63
66
|
- data_slice (List[Dict[str, Any]]): List of dictionaries containing TV show details to display.
|
|
64
67
|
"""
|
|
68
|
+
if not data_slice:
|
|
69
|
+
logging.error("Nothing to display.")
|
|
70
|
+
return
|
|
71
|
+
|
|
72
|
+
if not self.column_info:
|
|
73
|
+
logging.error("Error: Column information not configured.")
|
|
74
|
+
return
|
|
75
|
+
|
|
65
76
|
table = Table(border_style="white")
|
|
66
77
|
|
|
67
78
|
# Add columns dynamically based on provided column information
|
|
@@ -72,8 +83,9 @@ class TVShowManager:
|
|
|
72
83
|
|
|
73
84
|
# Add rows dynamically based on available TV show data
|
|
74
85
|
for entry in data_slice:
|
|
75
|
-
|
|
76
|
-
|
|
86
|
+
if entry:
|
|
87
|
+
row_data = [str(entry.get(col_name, '')) for col_name in self.column_info.keys()]
|
|
88
|
+
table.add_row(*row_data)
|
|
77
89
|
|
|
78
90
|
self.console.print(table)
|
|
79
91
|
|
|
@@ -125,6 +137,14 @@ class TVShowManager:
|
|
|
125
137
|
Returns:
|
|
126
138
|
str: Last command executed before breaking out of the loop.
|
|
127
139
|
"""
|
|
140
|
+
if not self.tv_shows:
|
|
141
|
+
logging.error("Error: No data available for display.")
|
|
142
|
+
return ""
|
|
143
|
+
|
|
144
|
+
if not self.column_info:
|
|
145
|
+
logging.error("Error: Columns not configured.")
|
|
146
|
+
return ""
|
|
147
|
+
|
|
128
148
|
total_items = len(self.tv_shows)
|
|
129
149
|
last_command = ""
|
|
130
150
|
is_telegram = config_manager.get_bool('DEFAULT', 'telegram_bot')
|
|
@@ -132,9 +152,17 @@ class TVShowManager:
|
|
|
132
152
|
|
|
133
153
|
while True:
|
|
134
154
|
start_message()
|
|
135
|
-
|
|
155
|
+
|
|
156
|
+
# Check and adjust slice indices if out of bounds
|
|
157
|
+
current_slice = self.tv_shows[self.slice_start:self.slice_end]
|
|
158
|
+
if not current_slice and total_items > 0:
|
|
159
|
+
self.slice_start = 0
|
|
160
|
+
self.slice_end = min(self.step, total_items)
|
|
161
|
+
current_slice = self.tv_shows[self.slice_start:self.slice_end]
|
|
162
|
+
|
|
163
|
+
self.display_data(current_slice)
|
|
136
164
|
|
|
137
|
-
#
|
|
165
|
+
# Resto del codice rimane uguale...
|
|
138
166
|
research_func = next((
|
|
139
167
|
f for f in get_call_stack()
|
|
140
168
|
if f['function'] == 'search' and f['script'] == '__init__.py'
|
|
@@ -225,5 +253,9 @@ class TVShowManager:
|
|
|
225
253
|
return last_command
|
|
226
254
|
|
|
227
255
|
def clear(self) -> None:
|
|
228
|
-
"""
|
|
229
|
-
|
|
256
|
+
"""
|
|
257
|
+
Clear all TV shows data.
|
|
258
|
+
"""
|
|
259
|
+
self.tv_shows = []
|
|
260
|
+
self.slice_start = 0
|
|
261
|
+
self.slice_end = self.step
|
StreamingCommunity/run.py
CHANGED
|
@@ -360,15 +360,24 @@ def setup_argument_parser(search_functions):
|
|
|
360
360
|
|
|
361
361
|
# Add arguments
|
|
362
362
|
parser.add_argument("script_id", nargs="?", default="unknown", help="ID dello script")
|
|
363
|
-
parser.add_argument('--
|
|
363
|
+
parser.add_argument('-s', '--search', default=None, help='Search terms')
|
|
364
|
+
parser.add_argument('--global', action='store_true', help='Global search across sites')
|
|
364
365
|
parser.add_argument('--not_close', type=bool, help='Keep console open after execution')
|
|
365
|
-
|
|
366
|
-
parser.add_argument('--default_audio_worker', type=int, help='Audio workers for M3U8 download (default: 12)')
|
|
366
|
+
|
|
367
367
|
parser.add_argument('--specific_list_audio', type=str, help='Audio languages (e.g., ita,eng)')
|
|
368
368
|
parser.add_argument('--specific_list_subtitles', type=str, help='Subtitle languages (e.g., eng,spa)')
|
|
369
|
-
parser.add_argument('--
|
|
369
|
+
parser.add_argument('--force_resolution', type=str, choices=["Best", "Worst", "720p", "1080p", "480p", "360p"],
|
|
370
|
+
help='Choose video resolution:\n'
|
|
371
|
+
' "Best": Highest available resolution\n'
|
|
372
|
+
' "Worst": Lowest available resolution\n'
|
|
373
|
+
' "720p": Force 720p resolution\n'
|
|
374
|
+
' Specific resolutions:\n'
|
|
375
|
+
' - 1080p (1920x1080)\n'
|
|
376
|
+
' - 720p (1280x720)\n'
|
|
377
|
+
' - 480p (640x480)\n'
|
|
378
|
+
' - 360p (640x360)')
|
|
379
|
+
|
|
370
380
|
parser.add_argument('--category', type=int, help='Category (1: anime, 2: film_&_serie, 3: serie, 4: torrent)')
|
|
371
|
-
parser.add_argument('-s', '--search', default=None, help='Search terms')
|
|
372
381
|
parser.add_argument('--auto-first', action='store_true', help='Auto-download first result (use with --site and --search)')
|
|
373
382
|
parser.add_argument('--site', type=str, help='Site by name or index')
|
|
374
383
|
|
|
@@ -380,10 +389,8 @@ def apply_config_updates(args):
|
|
|
380
389
|
config_updates = {}
|
|
381
390
|
|
|
382
391
|
arg_mappings = {
|
|
383
|
-
'add_siteName': 'DEFAULT.add_siteName',
|
|
384
392
|
'not_close': 'DEFAULT.not_close',
|
|
385
|
-
'
|
|
386
|
-
'default_audio_worker': 'M3U8_DOWNLOAD.default_audio_worker'
|
|
393
|
+
'force_resolution': 'M3U8_CONVERSION.force_resolution',
|
|
387
394
|
}
|
|
388
395
|
|
|
389
396
|
for arg_name, config_key in arg_mappings.items():
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: StreamingCommunity
|
|
3
|
-
Version: 3.3.
|
|
3
|
+
Version: 3.3.6
|
|
4
4
|
Home-page: https://github.com/Arrowar/StreamingCommunity
|
|
5
5
|
Author: Arrowar
|
|
6
6
|
Project-URL: Bug Reports, https://github.com/Arrowar/StreamingCommunity/issues
|
|
@@ -45,7 +45,9 @@ Dynamic: requires-python
|
|
|
45
45
|
[](https://github.com/Arrowar/StreamingCommunity/blob/main/LICENSE)
|
|
46
46
|
|
|
47
47
|
## 💝 Support the Project
|
|
48
|
-
|
|
48
|
+
<a href='https://ko-fi.com/E1E11LVC83' target='_blank'>
|
|
49
|
+
<img height='36' style='border:0px;height:36px;' src='https://storage.ko-fi.com/cdn/kofi4.png?v=6' border='0' alt='Buy Me a Coffee at ko-fi.com' />
|
|
50
|
+
</a>
|
|
49
51
|
|
|
50
52
|
## 🚀 Download & Install
|
|
51
53
|
[](https://github.com/Arrowar/StreamingCommunity/releases/latest/download/StreamingCommunity_win.exe)
|
|
@@ -62,50 +64,44 @@ Dynamic: requires-python
|
|
|
62
64
|
---
|
|
63
65
|
|
|
64
66
|
## 📖 Table of Contents
|
|
65
|
-
- [Installation](#
|
|
66
|
-
- [Quick Start](#quick-start)
|
|
67
|
-
- [Downloaders](#downloaders)
|
|
68
|
-
- [Configuration](#configuration)
|
|
69
|
-
- [Login](.github/.site/login.md)
|
|
70
|
-
- [
|
|
71
|
-
- [
|
|
72
|
-
- [
|
|
73
|
-
- [
|
|
74
|
-
- [
|
|
75
|
-
- [
|
|
67
|
+
- ⚙️ [Installation](#installation)
|
|
68
|
+
- 🚀 [Quick Start](#quick-start)
|
|
69
|
+
- 📥 [Downloaders](#downloaders)
|
|
70
|
+
- 🛠️ [Configuration](#configuration)
|
|
71
|
+
- 🔐 [Login](.github/.site/login.md)
|
|
72
|
+
- 🌐 [Domain](https://arrowar.github.io/StreamingCommunity)
|
|
73
|
+
- 💡 [Usage Examples](#usage-examples)
|
|
74
|
+
- 🔍 [Global Search](#global-search)
|
|
75
|
+
- 🧩 [Advanced Features](#advanced-options)
|
|
76
|
+
- 🐳 [Deployment](#docker)
|
|
77
|
+
- 🎓 [Tutorials](#tutorials)
|
|
78
|
+
- 🔗 [Related Projects](#useful-project)
|
|
76
79
|
|
|
77
80
|
---
|
|
78
81
|
|
|
79
|
-
##
|
|
82
|
+
## Installation
|
|
80
83
|
|
|
81
|
-
|
|
84
|
+
### Prerequisites
|
|
85
|
+
Make sure you have Python installed on your system:
|
|
86
|
+
- **Windows**: Download from [python.org](https://python.org) or install via Microsoft Store
|
|
87
|
+
- **Linux**: `sudo apt install python3 python3-pip` (Ubuntu/Debian) or equivalent for your distro
|
|
88
|
+
- **MacOS**: `brew install python3` or download from [python.org](https://python.org)
|
|
82
89
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
90
|
+
### Dependencies
|
|
91
|
+
```bash
|
|
92
|
+
# Windows
|
|
86
93
|
pip install -r requirements.txt
|
|
87
|
-
```
|
|
88
94
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
```bash
|
|
95
|
+
# Linux/MacOS
|
|
92
96
|
pip3 install -r requirements.txt
|
|
93
|
-
# or alternatively:
|
|
94
|
-
python3 -m pip install -r requirements.txt
|
|
95
97
|
```
|
|
96
98
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
### On Windows:
|
|
101
|
-
|
|
102
|
-
```powershell
|
|
99
|
+
### Update
|
|
100
|
+
```bash
|
|
101
|
+
# Windows
|
|
103
102
|
python update.py
|
|
104
|
-
```
|
|
105
103
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
```bash
|
|
104
|
+
# Linux/MacOS
|
|
109
105
|
python3 update.py
|
|
110
106
|
```
|
|
111
107
|
|
|
@@ -113,26 +109,17 @@ python3 update.py
|
|
|
113
109
|
|
|
114
110
|
## Quick Start
|
|
115
111
|
|
|
116
|
-
|
|
112
|
+
**Via pip installation:**
|
|
117
113
|
```bash
|
|
118
114
|
StreamingCommunity
|
|
119
115
|
```
|
|
120
|
-
to start the application.
|
|
121
|
-
|
|
122
|
-
Run the script:
|
|
123
|
-
```bash
|
|
124
|
-
python run_streaming.py
|
|
125
|
-
```
|
|
126
116
|
|
|
127
117
|
**Manual execution:**
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
```powershell
|
|
118
|
+
```bash
|
|
119
|
+
# Windows
|
|
131
120
|
python test_run.py
|
|
132
|
-
```
|
|
133
121
|
|
|
134
|
-
|
|
135
|
-
```bash
|
|
122
|
+
# Linux/MacOS
|
|
136
123
|
python3 test_run.py
|
|
137
124
|
```
|
|
138
125
|
|
|
@@ -155,7 +142,7 @@ downloader = HLS_Downloader(
|
|
|
155
142
|
downloader.download()
|
|
156
143
|
```
|
|
157
144
|
|
|
158
|
-
See [HLS example](./Test/
|
|
145
|
+
See [HLS example](./Test/Downloads//HLS.py) for complete usage.
|
|
159
146
|
|
|
160
147
|
<summary>📽️ MP4</summary>
|
|
161
148
|
|
|
@@ -172,7 +159,7 @@ downloader = MP4_downloader(
|
|
|
172
159
|
downloader.download()
|
|
173
160
|
```
|
|
174
161
|
|
|
175
|
-
See [MP4 example](./Test/
|
|
162
|
+
See [MP4 example](./Test/Downloads/MP4.py) for complete usage.
|
|
176
163
|
|
|
177
164
|
<summary>🧲 TOR</summary>
|
|
178
165
|
|
|
@@ -188,7 +175,7 @@ client.add_magnet_link("magnet:?xt=urn:btih:example_hash&dn=example_name", save_
|
|
|
188
175
|
client.start_download()
|
|
189
176
|
```
|
|
190
177
|
|
|
191
|
-
See [Torrent example](./Test/
|
|
178
|
+
See [Torrent example](./Test/Downloads/TOR.py) for complete usage.
|
|
192
179
|
|
|
193
180
|
<summary>🎞️ DASH</summary>
|
|
194
181
|
|
|
@@ -210,7 +197,7 @@ if dash_process.download_and_decrypt():
|
|
|
210
197
|
dash_process.get_status()
|
|
211
198
|
```
|
|
212
199
|
|
|
213
|
-
See [DASH example](./Test/
|
|
200
|
+
See [DASH example](./Test/Downloads/DASH.py) for complete usage.
|
|
214
201
|
|
|
215
202
|
---
|
|
216
203
|
|