StreamingCommunity 3.3.0__py3-none-any.whl → 3.3.1__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.

Files changed (27) hide show
  1. StreamingCommunity/Api/Site/altadefinizione/__init__.py +37 -17
  2. StreamingCommunity/Api/Site/animeunity/__init__.py +36 -16
  3. StreamingCommunity/Api/Site/animeworld/__init__.py +50 -6
  4. StreamingCommunity/Api/Site/crunchyroll/__init__.py +42 -16
  5. StreamingCommunity/Api/Site/crunchyroll/site.py +1 -1
  6. StreamingCommunity/Api/Site/guardaserie/__init__.py +50 -6
  7. StreamingCommunity/Api/Site/mediasetinfinity/__init__.py +43 -5
  8. StreamingCommunity/Api/Site/mediasetinfinity/film.py +1 -1
  9. StreamingCommunity/Api/Site/mediasetinfinity/site.py +6 -3
  10. StreamingCommunity/Api/Site/mediasetinfinity/util/ScrapeSerie.py +6 -7
  11. StreamingCommunity/Api/Site/mediasetinfinity/util/get_license.py +162 -0
  12. StreamingCommunity/Api/Site/raiplay/__init__.py +45 -14
  13. StreamingCommunity/Api/Site/raiplay/series.py +9 -5
  14. StreamingCommunity/Api/Site/streamingcommunity/__init__.py +7 -2
  15. StreamingCommunity/Api/Site/streamingwatch/__init__.py +44 -14
  16. StreamingCommunity/Lib/Downloader/DASH/downloader.py +87 -55
  17. StreamingCommunity/Lib/Downloader/HLS/downloader.py +18 -6
  18. StreamingCommunity/Lib/Downloader/HLS/segments.py +1 -1
  19. StreamingCommunity/Lib/FFmpeg/command.py +66 -7
  20. StreamingCommunity/Lib/FFmpeg/util.py +16 -13
  21. StreamingCommunity/Upload/version.py +1 -1
  22. {streamingcommunity-3.3.0.dist-info → streamingcommunity-3.3.1.dist-info}/METADATA +2 -11
  23. {streamingcommunity-3.3.0.dist-info → streamingcommunity-3.3.1.dist-info}/RECORD +27 -27
  24. {streamingcommunity-3.3.0.dist-info → streamingcommunity-3.3.1.dist-info}/WHEEL +0 -0
  25. {streamingcommunity-3.3.0.dist-info → streamingcommunity-3.3.1.dist-info}/entry_points.txt +0 -0
  26. {streamingcommunity-3.3.0.dist-info → streamingcommunity-3.3.1.dist-info}/licenses/LICENSE +0 -0
  27. {streamingcommunity-3.3.0.dist-info → streamingcommunity-3.3.1.dist-info}/top_level.txt +0 -0
@@ -6,11 +6,13 @@ import shutil
6
6
 
7
7
  # External libraries
8
8
  from rich.console import Console
9
+ from rich.panel import Panel
9
10
 
10
11
 
11
12
  # Internal utilities
12
13
  from StreamingCommunity.Util.config_json import config_manager
13
- from StreamingCommunity.Lib.FFmpeg.command import join_audios, join_video
14
+ from StreamingCommunity.Util.os import internet_manager
15
+ from ...FFmpeg import print_duration_table
14
16
 
15
17
 
16
18
  # Logic class
@@ -20,6 +22,7 @@ from .decrypt import decrypt_with_mp4decrypt
20
22
  from .cdm_helpher import get_widevine_keys
21
23
 
22
24
 
25
+
23
26
  # Config
24
27
  DOWNLOAD_SPECIFIC_AUDIO = config_manager.get_list('M3U8_DOWNLOAD', 'specific_list_audio')
25
28
  FILTER_CUSTOM_REOLUTION = str(config_manager.get('M3U8_CONVERSION', 'force_resolution')).strip().lower()
@@ -35,8 +38,8 @@ class DASH_Downloader:
35
38
  self.cdm_device = cdm_device
36
39
  self.license_url = license_url
37
40
  self.mpd_url = mpd_url
38
- self.original_output_path = os.path.abspath(str(output_path))
39
- self.out_path = os.path.splitext(self.original_output_path)[0]
41
+ self.out_path = os.path.splitext(os.path.abspath(str(output_path)))[0]
42
+ self.original_output_path = output_path
40
43
  self.parser = None
41
44
  self._setup_temp_dirs()
42
45
 
@@ -94,12 +97,35 @@ class DASH_Downloader:
94
97
  self.error = None
95
98
  self.stopped = False
96
99
 
100
+ # Fetch keys immediately after obtaining PSSH
101
+ if not self.parser.pssh:
102
+ console.print("[red]No PSSH found: segments are not encrypted, skipping decryption.")
103
+ self.download_segments(clear=True)
104
+ return True
105
+
106
+ keys = get_widevine_keys(
107
+ pssh=self.parser.pssh,
108
+ license_url=self.license_url,
109
+ cdm_device_path=self.cdm_device,
110
+ headers=custom_headers,
111
+ payload=custom_payload
112
+ )
113
+
114
+ if not keys:
115
+ console.print("[red]No keys found, cannot proceed with download.[/red]")
116
+ return False
117
+
118
+ # Extract the first key for decryption
119
+ key = keys[0]
120
+ KID = key['kid']
121
+ KEY = key['key']
122
+
97
123
  for typ in ["video", "audio"]:
98
124
  rep = self.get_representation_by_type(typ)
99
125
  if rep:
100
126
  encrypted_path = os.path.join(self.encrypted_dir, f"{rep['id']}_encrypted.m4s")
101
127
 
102
- # If m4s file doesn't exist start downloading
128
+ # If m4s file doesn't exist, start downloading
103
129
  if not os.path.exists(encrypted_path):
104
130
  downloader = MPD_Segments(
105
131
  tmp_folder=self.encrypted_dir,
@@ -124,28 +150,6 @@ class DASH_Downloader:
124
150
  self.error = str(ex)
125
151
  return False
126
152
 
127
- if not self.parser.pssh:
128
- print("No PSSH found: segments are not encrypted, skipping decryption.")
129
- self.download_segments(clear=True)
130
- return True
131
-
132
- keys = get_widevine_keys(
133
- pssh=self.parser.pssh,
134
- license_url=self.license_url,
135
- cdm_device_path=self.cdm_device,
136
- headers=custom_headers,
137
- payload=custom_payload
138
- )
139
-
140
- if not keys:
141
- self.error = f"No key found, cannot decrypt {typ}"
142
- print(self.error)
143
- return False
144
-
145
- key = keys[0]
146
- KID = key['kid']
147
- KEY = key['key']
148
-
149
153
  decrypted_path = os.path.join(self.decrypted_dir, f"{typ}.mp4")
150
154
  result_path = decrypt_with_mp4decrypt(
151
155
  encrypted_path, KID, KEY, output_path=decrypted_path
@@ -169,46 +173,74 @@ class DASH_Downloader:
169
173
  pass
170
174
 
171
175
  def finalize_output(self):
172
- video_file = os.path.join(self.decrypted_dir, "video.mp4")
173
- audio_file = os.path.join(self.decrypted_dir, "audio.mp4")
174
-
175
- # fallback: if one of the two is missing, look in encrypted
176
- if not os.path.exists(video_file):
177
- for f in os.listdir(self.encrypted_dir):
178
- if f.endswith("_encrypted.m4s") and ("video" in f or f.startswith("1_")):
179
- video_file = os.path.join(self.encrypted_dir, f)
180
- break
181
- if not os.path.exists(audio_file):
182
- for f in os.listdir(self.encrypted_dir):
183
- if f.endswith("_encrypted.m4s") and ("audio" in f or f.startswith("0_")):
184
- audio_file = os.path.join(self.encrypted_dir, f)
185
- break
186
-
187
- # Usa il nome file originale per il file finale
176
+
177
+ # Use the original output path for the final file
188
178
  output_file = self.original_output_path
179
+
180
+ # Set the output file path for status tracking
181
+ self.output_file = output_file
182
+ use_shortest = False
189
183
 
190
- if os.path.exists(video_file) and os.path.exists(audio_file):
184
+ """if os.path.exists(video_file) and os.path.exists(audio_file):
191
185
  audio_tracks = [{"path": audio_file}]
192
- join_audios(video_file, audio_tracks, output_file)
186
+ out_audio_path, use_shortest = join_audios(video_file, audio_tracks, output_file)
187
+
193
188
  elif os.path.exists(video_file):
194
- join_video(video_file, output_file, codec=None)
189
+ out_video_path = join_video(video_file, output_file, codec=None)
190
+
195
191
  else:
196
192
  print("Video file missing, cannot export")
193
+ return None
194
+ """
197
195
 
198
- # Clean up: delete all tmp
196
+ # Handle failed sync case
197
+ if use_shortest:
198
+ new_filename = output_file.replace(".mp4", "_failed_sync.mp4")
199
+ os.rename(output_file, new_filename)
200
+ output_file = new_filename
201
+ self.output_file = new_filename
202
+
203
+ # Display file information
204
+ if os.path.exists(output_file):
205
+ file_size = internet_manager.format_file_size(os.path.getsize(output_file))
206
+ duration = print_duration_table(output_file, description=False, return_string=True)
207
+ panel_content = (
208
+ f"[cyan]File size: [bold red]{file_size}[/bold red]\n"
209
+ f"[cyan]Duration: [bold]{duration}[/bold]\n"
210
+ f"[cyan]Output: [bold]{os.path.abspath(output_file)}[/bold]"
211
+ )
212
+
213
+ console.print(Panel(
214
+ panel_content,
215
+ title=f"{os.path.basename(output_file.replace('.mp4', ''))}",
216
+ border_style="green"
217
+ ))
218
+
219
+ # Clean up: delete only the tmp directory, not the main directory
199
220
  if os.path.exists(self.tmp_dir):
200
221
  shutil.rmtree(self.tmp_dir, ignore_errors=True)
201
222
 
202
- # Rimuovi la cartella principale se è vuota
203
- try:
204
- if os.path.exists(self.out_path) and not os.listdir(self.out_path):
205
- os.rmdir(self.out_path)
206
- except Exception as e:
207
- print(f"[WARN] Impossibile eliminare la cartella {self.out_path}: {e}")
223
+ # Only remove the temp base directory if it was created specifically for this download
224
+ # and if the final output is NOT inside this directory
225
+ output_dir = os.path.dirname(self.original_output_path)
208
226
 
227
+ # Check if out_path is different from the actual output directory
228
+ # and if it's empty, then it's safe to remove
229
+ if (self.out_path != output_dir and
230
+ os.path.exists(self.out_path) and
231
+ not os.listdir(self.out_path)):
232
+ try:
233
+ os.rmdir(self.out_path)
234
+ except Exception as e:
235
+ print(f"[WARN] Cannot remove directory {self.out_path}: {e}")
209
236
 
210
- return self.output_file
211
-
237
+ # Verify the final file exists before returning
238
+ if os.path.exists(output_file):
239
+ return output_file
240
+ else:
241
+ self.error = "Final output file was not created successfully"
242
+ return None
243
+
212
244
  def get_status(self):
213
245
  """
214
246
  Returns a dict with 'path', 'error', and 'stopped' for external use.
@@ -217,4 +249,4 @@ class DASH_Downloader:
217
249
  "path": self.output_file,
218
250
  "error": self.error,
219
251
  "stopped": self.stopped
220
- }
252
+ }
@@ -360,6 +360,7 @@ class MergeManager:
360
360
  """
361
361
  video_file = os.path.join(self.temp_dir, 'video', '0.ts')
362
362
  merged_file = video_file
363
+ use_shortest = False
363
364
 
364
365
  if not self.audio_streams and not self.sub_streams:
365
366
  merged_file = join_video(
@@ -376,7 +377,7 @@ class MergeManager:
376
377
  } for a in self.audio_streams]
377
378
 
378
379
  merged_audio_path = os.path.join(self.temp_dir, 'merged_audio.mp4')
379
- merged_file = join_audios(
380
+ merged_file, use_shortest = join_audios(
380
381
  video_path=video_file,
381
382
  audio_tracks=audio_tracks,
382
383
  out_path=merged_audio_path,
@@ -396,7 +397,7 @@ class MergeManager:
396
397
  out_path=merged_subs_path
397
398
  )
398
399
 
399
- return merged_file
400
+ return merged_file, use_shortest
400
401
 
401
402
 
402
403
  class HLS_Downloader:
@@ -467,9 +468,9 @@ class HLS_Downloader:
467
468
  sub_streams=self.m3u8_manager.sub_streams
468
469
  )
469
470
 
470
- final_file = self.merge_manager.merge()
471
+ final_file, use_shortest = self.merge_manager.merge()
471
472
  self.path_manager.move_final_file(final_file)
472
- self._print_summary()
473
+ self._print_summary(use_shortest)
473
474
  self.path_manager.cleanup()
474
475
 
475
476
  return {
@@ -495,7 +496,7 @@ class HLS_Downloader:
495
496
  'stopped': False
496
497
  }
497
498
 
498
- def _print_summary(self):
499
+ def _print_summary(self, use_shortest):
499
500
  """Prints download summary including file size, duration, and any missing segments."""
500
501
  if TELEGRAM_BOT:
501
502
  bot = get_bot_instance()
@@ -523,7 +524,18 @@ class HLS_Downloader:
523
524
 
524
525
  if missing_ts:
525
526
  panel_content += f"\n{missing_info}"
526
- os.rename(self.path_manager.output_path, self.path_manager.output_path.replace(".mp4", "_failed.mp4"))
527
+
528
+ new_filename = self.path_manager.output_path
529
+ if missing_ts and use_shortest:
530
+ new_filename = new_filename.replace(".mp4", "_failed_sync_ts.mp4")
531
+ elif missing_ts:
532
+ new_filename = new_filename.replace(".mp4", "_failed_ts.mp4")
533
+ elif use_shortest:
534
+ new_filename = new_filename.replace(".mp4", "_failed_sync.mp4")
535
+
536
+ if missing_ts or use_shortest:
537
+ os.rename(self.path_manager.output_path, new_filename)
538
+ self.path_manager.output_path = new_filename
527
539
 
528
540
  console.print(Panel(
529
541
  panel_content,
@@ -249,7 +249,7 @@ class M3U8_Segments:
249
249
  self.info_nRetry += 1
250
250
 
251
251
  if attempt + 1 == REQUEST_MAX_RETRY:
252
- console.log(f"[red]Final retry failed for segment: {index}")
252
+ console.print(f"[red]Final retry failed for segment: {index}")
253
253
  self.queue.put((index, None)) # Marker for failed segment
254
254
  progress_bar.update(1)
255
255
  self.info_nFailed += 1
@@ -15,7 +15,7 @@ from StreamingCommunity.Util.os import os_manager, suppress_output, get_ffmpeg_p
15
15
 
16
16
 
17
17
  # Logic class
18
- from .util import need_to_force_to_ts, check_duration_v_a
18
+ from .util import need_to_force_to_ts, check_duration_v_a, get_video_duration
19
19
  from .capture import capture_ffmpeg_real_time
20
20
  from ..M3U8 import M3U8_Codec
21
21
 
@@ -99,6 +99,14 @@ def join_video(video_path: str, out_path: str, codec: M3U8_Codec = None):
99
99
  - out_path (str): The path to save the output file.
100
100
  - codec (M3U8_Codec): The video codec to use. Defaults to 'copy'.
101
101
  """
102
+ if video_path is None:
103
+ console.log("[red]No video path provided for joining.")
104
+ return None
105
+
106
+ if out_path is None:
107
+ console.log("[red]No output path provided for joining.")
108
+ return None
109
+
102
110
  ffmpeg_cmd = [get_ffmpeg_path()]
103
111
 
104
112
  # Enabled the use of gpu
@@ -175,10 +183,50 @@ def join_audios(video_path: str, audio_tracks: List[Dict[str, str]], out_path: s
175
183
  Parameters:
176
184
  - video_path (str): The path to the video file.
177
185
  - audio_tracks (list[dict[str, str]]): A list of dictionaries containing information about audio tracks.
178
- Each dictionary should contain the 'path' key with the path to the audio file.
186
+ Each dictionary should contain the 'path' and 'name' keys.
179
187
  - out_path (str): The path to save the output file.
180
188
  """
181
- video_audio_same_duration, duration_diff = check_duration_v_a(video_path, audio_tracks[0].get('path'))
189
+ if video_path is None:
190
+ console.log("[red]No video path provided for joining audios.")
191
+ return None, False
192
+
193
+ if audio_tracks is None or len(audio_tracks) == 0:
194
+ console.log("[red]No audio tracks provided for joining.")
195
+ return None, False
196
+
197
+ if out_path is None:
198
+ console.log("[red]No output path provided for joining audios.")
199
+ return None, False
200
+
201
+ use_shortest = False
202
+ duration_diffs = []
203
+
204
+ # Get video duration first
205
+ video_duration = get_video_duration(video_path, None)
206
+
207
+ for audio_track in audio_tracks:
208
+ audio_path = audio_track.get('path')
209
+ audio_lang = audio_track.get('name', 'unknown')
210
+ audio_duration, diff = check_duration_v_a(video_path, audio_path)
211
+
212
+ duration_diffs.append({
213
+ 'language': audio_lang,
214
+ 'difference': diff,
215
+ 'has_error': diff > 0.5,
216
+ 'video_duration': video_duration,
217
+ 'audio_duration': audio_duration
218
+ })
219
+
220
+ if diff > 0.5:
221
+ use_shortest = True
222
+ console.log("[red]Warning: Some audio tracks have duration differences (>0.5s)")
223
+
224
+ # Print duration differences for each track
225
+ if use_shortest:
226
+ for track in duration_diffs:
227
+ color = "red" if track['has_error'] else "green"
228
+ console.print(f"[{color}]Audio {track['language']}: Video duration: {track['video_duration']:.2f}s, Audio duration: {track['audio_duration']:.2f}s, Difference: {track['difference']:.2f}s[/{color}]")
229
+
182
230
 
183
231
  # Start command with locate ffmpeg
184
232
  ffmpeg_cmd = [get_ffmpeg_path()]
@@ -238,9 +286,8 @@ def join_audios(video_path: str, audio_tracks: List[Dict[str, str]], out_path: s
238
286
  else:
239
287
  ffmpeg_cmd.extend(['-preset', 'fast'])
240
288
 
241
- # Use shortest input path for video and audios
242
- if not video_audio_same_duration:
243
- console.log(f"[red]Use shortest input (Duration difference: {duration_diff:.2f} seconds)...")
289
+ # Use shortest input path if any audio track has significant difference
290
+ if use_shortest:
244
291
  ffmpeg_cmd.extend(['-shortest', '-strict', 'experimental'])
245
292
 
246
293
  # Overwrite
@@ -261,7 +308,7 @@ def join_audios(video_path: str, audio_tracks: List[Dict[str, str]], out_path: s
261
308
  capture_ffmpeg_real_time(ffmpeg_cmd, "[cyan]Join audio")
262
309
  print()
263
310
 
264
- return out_path
311
+ return out_path, use_shortest
265
312
 
266
313
 
267
314
  def join_subtitle(video_path: str, subtitles_list: List[Dict[str, str]], out_path: str):
@@ -274,6 +321,18 @@ def join_subtitle(video_path: str, subtitles_list: List[Dict[str, str]], out_pat
274
321
  Each dictionary should contain the 'path' key with the path to the subtitle file and the 'name' key with the name of the subtitle.
275
322
  - out_path (str): The path to save the output file.
276
323
  """
324
+ if video_path is None:
325
+ console.log("[red]No video path provided for joining subtitles.")
326
+ return None
327
+
328
+ if subtitles_list is None or len(subtitles_list) == 0:
329
+ console.log("[red]No subtitles provided for joining.")
330
+ return None
331
+
332
+ if out_path is None:
333
+ console.log("[red]No output path provided for joining subtitles.")
334
+ return None
335
+
277
336
  ffmpeg_cmd = [get_ffmpeg_path(), "-i", video_path]
278
337
 
279
338
  # Add subtitle input files first
@@ -47,15 +47,16 @@ def has_audio_stream(video_path: str) -> bool:
47
47
  return False
48
48
 
49
49
 
50
- def get_video_duration(file_path: str) -> float:
50
+ def get_video_duration(file_path: str, file_type: str = "file") -> float:
51
51
  """
52
- Get the duration of a video file.
52
+ Get the duration of a media file (video or audio).
53
53
 
54
54
  Parameters:
55
- - file_path (str): The path to the video file.
55
+ - file_path (str): The path to the media file.
56
+ - file_type (str): The type of the file ('video' or 'audio'). Defaults to 'file'.
56
57
 
57
58
  Returns:
58
- (float): The duration of the video in seconds if successful, None if there's an error.
59
+ (float): The duration of the media file in seconds if successful, None if there's an error.
59
60
  """
60
61
  try:
61
62
  ffprobe_cmd = [get_ffprobe_path(), '-v', 'error', '-show_format', '-print_format', 'json', file_path]
@@ -64,23 +65,23 @@ def get_video_duration(file_path: str) -> float:
64
65
  # Use a with statement to ensure the subprocess is cleaned up properly
65
66
  with subprocess.Popen(ffprobe_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) as proc:
66
67
  stdout, stderr = proc.communicate()
67
-
68
+
68
69
  if proc.returncode != 0:
69
70
  logging.error(f"Error: {stderr}")
70
71
  return None
71
-
72
+
72
73
  # Parse JSON output
73
74
  probe_result = json.loads(stdout)
74
75
 
75
- # Extract duration from the video information
76
+ # Extract duration from the media information
76
77
  try:
77
78
  return float(probe_result['format']['duration'])
78
-
79
+
79
80
  except Exception:
80
81
  return 1
81
82
 
82
83
  except Exception as e:
83
- logging.error(f"Get video duration error: {e}")
84
+ logging.error(f"Get {file_type} duration error: {e}, ffprobe path: {get_ffprobe_path()}, file path: {file_path}")
84
85
  sys.exit(0)
85
86
 
86
87
 
@@ -242,20 +243,22 @@ def check_duration_v_a(video_path, audio_path, tolerance=1.0):
242
243
  Returns:
243
244
  - tuple: (bool, float) -> True if the duration of the video and audio matches, False otherwise, along with the difference in duration.
244
245
  """
245
- video_duration = get_video_duration(video_path)
246
- audio_duration = get_video_duration(audio_path)
246
+ video_duration = get_video_duration(video_path, file_type="video")
247
+ audio_duration = get_video_duration(audio_path, file_type="audio")
247
248
 
248
249
  # Check if either duration is None and specify which one is None
249
250
  if video_duration is None and audio_duration is None:
250
251
  console.print("[yellow]Warning: Both video and audio durations are None. Returning 0 as duration difference.[/yellow]")
251
252
  return False, 0.0
253
+
252
254
  elif video_duration is None:
253
255
  console.print("[yellow]Warning: Video duration is None. Returning 0 as duration difference.[/yellow]")
254
256
  return False, 0.0
257
+
255
258
  elif audio_duration is None:
256
259
  console.print("[yellow]Warning: Audio duration is None. Returning 0 as duration difference.[/yellow]")
257
260
  return False, 0.0
258
-
261
+
259
262
  # Calculate the duration difference
260
263
  duration_difference = abs(video_duration - audio_duration)
261
264
 
@@ -263,4 +266,4 @@ def check_duration_v_a(video_path, audio_path, tolerance=1.0):
263
266
  if duration_difference <= tolerance:
264
267
  return True, duration_difference
265
268
  else:
266
- return False, duration_difference
269
+ return False, duration_difference
@@ -1,5 +1,5 @@
1
1
  __title__ = 'StreamingCommunity'
2
- __version__ = '3.3.0'
2
+ __version__ = '3.3.1'
3
3
  __author__ = 'Arrowar'
4
4
  __description__ = 'A command-line program to download film'
5
5
  __copyright__ = 'Copyright 2025'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: StreamingCommunity
3
- Version: 3.3.0
3
+ Version: 3.3.1
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
@@ -25,6 +25,7 @@ Requires-Dist: ua-generator
25
25
  Requires-Dist: qbittorrent-api
26
26
  Requires-Dist: pyTelegramBotAPI
27
27
  Requires-Dist: pywidevine
28
+ Requires-Dist: seleniumbase
28
29
  Dynamic: author
29
30
  Dynamic: description
30
31
  Dynamic: description-content-type
@@ -906,10 +907,6 @@ python3 telegram_bot.py
906
907
  ```
907
908
  </details>
908
909
 
909
- # SITE_LOGIN key
910
- To use some site, you may need a SITE_LOGIN key.
911
- See [guide.md](.github/.site/guide.md) for instructions on how to obtain it.
912
-
913
910
  # Tutorials
914
911
 
915
912
  - [Windows](https://www.youtube.com/watch?v=mZGqK4wdN-k)
@@ -917,17 +914,11 @@ See [guide.md](.github/.site/guide.md) for instructions on how to obtain it.
917
914
  - [Pypy](https://www.youtube.com/watch?v=C6m9ZKOK0p4)
918
915
  - [Compiled](https://www.youtube.com/watch?v=pm4lqsxkTVo)
919
916
 
920
- # To Do
921
-
922
- - To Finish [website API](https://github.com/Arrowar/StreamingCommunity/tree/test_gui_1)
923
- - To finish [website API 2](https://github.com/hydrosh/StreamingCommunity/tree/test_gui_1)
924
-
925
917
  ## Useful Project
926
918
 
927
919
  ### 🎯 [Unit3Dup](https://github.com/31December99/Unit3Dup)
928
920
  Bot in Python per la generazione e l'upload automatico di torrent su tracker basati su Unit3D.
929
921
 
930
-
931
922
  ### 🇮🇹 [MammaMia](https://github.com/UrloMythus/MammaMia)
932
923
  Addon per Stremio che consente lo streaming HTTPS di film, serie, anime e TV in diretta in lingua italiana.
933
924
 
@@ -11,50 +11,50 @@ StreamingCommunity/Api/Player/sweetpixel.py,sha256=AAdLSD7ASLuZNiBx6btr8S44Wkxtj
11
11
  StreamingCommunity/Api/Player/vixcloud.py,sha256=0DnukAIBqGqTmL9I6JkpAkHLMf1UG1D_J8c7zt6KDmU,6609
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=WjpNA-ohE6AIwYOVzacYqy7CR3fXfdf7PfIp69vk8js,5343
14
- StreamingCommunity/Api/Site/altadefinizione/__init__.py,sha256=fpFUhnjjRE2TXf1lNFBUoHH-WWyFQpXeG1xqkU_cQjw,4877
14
+ StreamingCommunity/Api/Site/altadefinizione/__init__.py,sha256=KCzeJZZ7rFu-64Zm7ik20XGFi8KK1wIeF6r7C3SHSkM,5553
15
15
  StreamingCommunity/Api/Site/altadefinizione/film.py,sha256=CQG1C9RGbPm_x89xgyTS8IqcP-lihNqCDY9ANghOlhE,3798
16
16
  StreamingCommunity/Api/Site/altadefinizione/series.py,sha256=--XPvUzL4K3KKaS41jZ9WToT3wxt2rUwblNoJOp8hs0,8280
17
17
  StreamingCommunity/Api/Site/altadefinizione/site.py,sha256=nrDmENnvWbW7iNO7OIGpQWJttzFGipZg0dsC8GiSEBU,2864
18
18
  StreamingCommunity/Api/Site/altadefinizione/util/ScrapeSerie.py,sha256=9iulNlnNAhTfI5iKNW3I6pZqYeYwovAswa13L3LPGDM,4251
19
- StreamingCommunity/Api/Site/animeunity/__init__.py,sha256=3eQ-AtLQCQK_ArTnnDit_NK5r04PuyPSSvEm4TUC9WE,4746
19
+ StreamingCommunity/Api/Site/animeunity/__init__.py,sha256=pmFGKSwpgfCGAXRK-thm4xZGG-J3Yeu-wl83rBoSaBI,5426
20
20
  StreamingCommunity/Api/Site/animeunity/film.py,sha256=Vqg6yag2siR-Y3ougBsV8mzdQXChxg6ghz_KVXFQ3pE,998
21
21
  StreamingCommunity/Api/Site/animeunity/serie.py,sha256=2PfpXblRpIrHC6gURfKYo16Vx_ZDcQX4CX03wAo8SCQ,5694
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
- StreamingCommunity/Api/Site/animeworld/__init__.py,sha256=kbsIxaAJtnEyFIbAS-IdCdPWrrynE_1TLzHtZzYYDWE,3783
24
+ StreamingCommunity/Api/Site/animeworld/__init__.py,sha256=v5ZuJVJCZINxG6_nZ_EQxRAyXmD6V35AlRokgx4kS2U,5139
25
25
  StreamingCommunity/Api/Site/animeworld/film.py,sha256=Ysp0k5AlrOsl19S9LV4nwVg8cjFf5w0FZRO9CiO6NxA,1748
26
26
  StreamingCommunity/Api/Site/animeworld/serie.py,sha256=b1yuBnLNqJ-IWEVqLnQuYv6VbUQ60a5YFpZbJrS3lnI,3486
27
27
  StreamingCommunity/Api/Site/animeworld/site.py,sha256=Zdp6ayA1L6hS1t0q4fclHs7J1eiD16Ta9isTc13Zye8,3746
28
28
  StreamingCommunity/Api/Site/animeworld/util/ScrapeSerie.py,sha256=S6sLtQt4Wvp4IVDho1uAXL8_-bbdj-RTRA1D7x9V8n8,3591
29
- StreamingCommunity/Api/Site/crunchyroll/__init__.py,sha256=tkjI_Spx6lOD95gVlSCwh2FeS1OMxKt1yXx6jYWayww,4893
29
+ StreamingCommunity/Api/Site/crunchyroll/__init__.py,sha256=8CuiONjE2G9q1UFrvTvToI7DVKw7RrCGUT2aACDoy2s,5555
30
30
  StreamingCommunity/Api/Site/crunchyroll/film.py,sha256=MgA8bwJEf6unT_uBBsLpMqRdbctkLYLGeBB-_fX1wvk,2615
31
31
  StreamingCommunity/Api/Site/crunchyroll/series.py,sha256=0JnPc9Bw02Ys-wmdAvcIbAlkyGHbw7ELemWVizWPl1k,7265
32
- StreamingCommunity/Api/Site/crunchyroll/site.py,sha256=0IRbC7xPyfdHGNffZzGkpCzqZ0zB3o0MWe5sQLVmRVk,4073
32
+ StreamingCommunity/Api/Site/crunchyroll/site.py,sha256=udMWlEi4fVG-yVcrsEP2JXdRZeYB_xwETTpPDzyBOno,4072
33
33
  StreamingCommunity/Api/Site/crunchyroll/util/ScrapeSerie.py,sha256=ZY6z4pT5q7igiNZnJAvE9x0WiORTvFSH-U_CpqOzusA,7855
34
34
  StreamingCommunity/Api/Site/crunchyroll/util/get_license.py,sha256=KpVvJbGUTLeVD-tt8r7ajBPWVT7Tm6GrKwzpW8CS-tg,6881
35
- StreamingCommunity/Api/Site/guardaserie/__init__.py,sha256=xKdy4puK4NI4ytFMZLqZXNeKaX8ub14mqpuelRFprSs,3800
35
+ StreamingCommunity/Api/Site/guardaserie/__init__.py,sha256=_VTPh3wBh3v73pSOIBxNqRV-DyhxD9iKj7DC6gpgm3I,5179
36
36
  StreamingCommunity/Api/Site/guardaserie/series.py,sha256=Q5i_nCAy8zAnublmWuujxrDwvP9XP2D207vrtYOdl_I,6566
37
37
  StreamingCommunity/Api/Site/guardaserie/site.py,sha256=_AtrkOb5xUnIfqp212y3p7kWb7BKJYwQHleSRgDOSYA,2239
38
38
  StreamingCommunity/Api/Site/guardaserie/util/ScrapeSerie.py,sha256=4wk2TVb4YDoPrhR2uuNijYuOpSt9mhcxwcXhmwTHPUY,4396
39
- StreamingCommunity/Api/Site/mediasetinfinity/__init__.py,sha256=xfGtJEJx3LE7e-0UN85PipJ0VUJ4vk2JZHXUkrN65-Q,4286
40
- StreamingCommunity/Api/Site/mediasetinfinity/film.py,sha256=L3jWSuxxO9SwRua9-zSF-nYfbwbmI4YG7YAM5yQlsDs,2308
39
+ StreamingCommunity/Api/Site/mediasetinfinity/__init__.py,sha256=ZmyJRjzdfnvlSsVG05IYCocvJsCyzfBiGPxjN1RAHmY,5428
40
+ StreamingCommunity/Api/Site/mediasetinfinity/film.py,sha256=ZfLbc3631UwmBThtA_X0nQew__hSl1l5ASOr9IdS71w,2334
41
41
  StreamingCommunity/Api/Site/mediasetinfinity/series.py,sha256=BtZaZmpJ7-tbMPmosRLbZG4-oaIMK3Q1CHV29A5xmng,6898
42
- StreamingCommunity/Api/Site/mediasetinfinity/site.py,sha256=n2c_Yg03fbOIx4ZYOg2FVoHM0rge16LIdACNvOyrURM,3872
43
- StreamingCommunity/Api/Site/mediasetinfinity/util/ScrapeSerie.py,sha256=jZiSfwrvfdqu_dM0LG55VIsntM66OhRHGTP0o_78eUM,11174
42
+ StreamingCommunity/Api/Site/mediasetinfinity/site.py,sha256=qCpc02RaEzIJll9m3IJOgDLQdU58MnGIXlBY5_GqU84,4374
43
+ StreamingCommunity/Api/Site/mediasetinfinity/util/ScrapeSerie.py,sha256=-zzBI2ugkIXaqlwTfFIMcmzpIXIbQiimRk_j9UVxZ5E,11154
44
44
  StreamingCommunity/Api/Site/mediasetinfinity/util/fix_mpd.py,sha256=B7uZfQ8X4p8KsiPVangFSs5rKKKpA3tavjPCdNrqyCc,1712
45
- StreamingCommunity/Api/Site/mediasetinfinity/util/get_license.py,sha256=CK1gmXlARi83DLrJzUeaQoFUOYiJtagtmG4AGUi11rY,5584
46
- StreamingCommunity/Api/Site/raiplay/__init__.py,sha256=m8kN-_apnOoPQ7DBQ4ZK2hEXmw6ITt2ja7pO0OhDX9Y,4641
45
+ StreamingCommunity/Api/Site/mediasetinfinity/util/get_license.py,sha256=hwHOsdLznJ_KIS5F6PnfFNxqP4nxfoassATxoLHN60E,11872
46
+ StreamingCommunity/Api/Site/raiplay/__init__.py,sha256=ExPwFYzTxyF8giuUb_kNaYgLqsiKdJ2faYhYDmsH6CM,5433
47
47
  StreamingCommunity/Api/Site/raiplay/film.py,sha256=Ep1Kcbvm2nZoHvaxW5Qbg4FBl9QZORM-NEi2obhQyos,3029
48
- StreamingCommunity/Api/Site/raiplay/series.py,sha256=EJx3ZUmXOGlha6J1vP93XVfh1VDAN_9fz_06dtdhIqI,7599
48
+ StreamingCommunity/Api/Site/raiplay/series.py,sha256=AojsVWqMk_o0i2zGVvXNVDeCUuNaPcyG-QUTtGquYkE,7829
49
49
  StreamingCommunity/Api/Site/raiplay/site.py,sha256=e0DoTIcSNLbk8uEBGgYCG6gbZ6yv-yo0Z-rT7PLNTlo,3182
50
50
  StreamingCommunity/Api/Site/raiplay/util/ScrapeSerie.py,sha256=KsEL8XSr_c1vvaPo-_AY9RGE7_eHZ8oN2iyZtB0ocrw,5880
51
51
  StreamingCommunity/Api/Site/raiplay/util/get_license.py,sha256=96Q5aSWhtxtmQl2yzylL-1x3jY24UpLLZlEE6YrO_gs,978
52
- StreamingCommunity/Api/Site/streamingcommunity/__init__.py,sha256=6ETXEt0c-TnPkuO8wHo6VCphqM2LKuVr811eLxNJbsc,5469
52
+ StreamingCommunity/Api/Site/streamingcommunity/__init__.py,sha256=lLQKaDrHyxehXmjpyx7Zf2rLYsBG22xo45rC_4oJhKc,5618
53
53
  StreamingCommunity/Api/Site/streamingcommunity/film.py,sha256=aA0tsDc5GCFFkrn_s2QKNcnyBYhK2S5OnDx29P1_rhA,2779
54
54
  StreamingCommunity/Api/Site/streamingcommunity/series.py,sha256=eLCeVjur2w2J1PgYzhe8dIJYGZus6YEyQr5H0YXazH4,9055
55
55
  StreamingCommunity/Api/Site/streamingcommunity/site.py,sha256=o1jdgF1nnUCnPnvybfc6a-0esHSYcRGjtUEOAXk6YAE,4131
56
56
  StreamingCommunity/Api/Site/streamingcommunity/util/ScrapeSerie.py,sha256=b-PWO1fP68yfptLb5X3i4M1PFZHKkqJh32yHgKsoIGs,5684
57
- StreamingCommunity/Api/Site/streamingwatch/__init__.py,sha256=K9gAeeJ6h7CQOhxXC2bUTXG4z9Dtv2R4Vv6XDSj9sik,4851
57
+ StreamingCommunity/Api/Site/streamingwatch/__init__.py,sha256=Nx8fedFHn4Ewy4iFDutyMiTzdYQKhfkJYJ8KlZjBOhg,5583
58
58
  StreamingCommunity/Api/Site/streamingwatch/film.py,sha256=B_9z9xzfuqEbzv-eVHuadvOKTcEiHhRU92Gk_f2u7Zs,1693
59
59
  StreamingCommunity/Api/Site/streamingwatch/series.py,sha256=nxGef_djMUZLAEDbHG-hbbly0eWagxPm8xu5aFIlSrI,6245
60
60
  StreamingCommunity/Api/Site/streamingwatch/site.py,sha256=KEtm-TeTuryAODXdvJAGPHauaq8cVl8QxHV6CDT1mzo,3474
@@ -68,17 +68,17 @@ StreamingCommunity/Api/Template/Util/manage_ep.py,sha256=JMGLj_SJY-K5YuvKISurEYy
68
68
  StreamingCommunity/Lib/Downloader/__init__.py,sha256=Zh92xTvBIEIjNQN22iXItG7_VqiDGbOpO5gOZDBdGxc,288
69
69
  StreamingCommunity/Lib/Downloader/DASH/cdm_helpher.py,sha256=-odu7Hc5dvzRXldQRlFalt6IVfvqi6XG_DCSyyqBGJ4,4767
70
70
  StreamingCommunity/Lib/Downloader/DASH/decrypt.py,sha256=y3F5zrED-FSQzwE9e5rTl07aWkg76qwFgxtziPpPVuQ,2352
71
- StreamingCommunity/Lib/Downloader/DASH/downloader.py,sha256=rswcxVXem_ddCbByZY1VbgdaQnhztsG02gMU7ZeD37s,8294
71
+ StreamingCommunity/Lib/Downloader/DASH/downloader.py,sha256=ioOWGidwsdU3WqayYZZ2N6sOPkrWxCgbZC0aoxCBL40,9341
72
72
  StreamingCommunity/Lib/Downloader/DASH/parser.py,sha256=QUyYhmu-zI2GieiNZaoOoDVPTclSKXsrdeToAtbC9yI,9858
73
73
  StreamingCommunity/Lib/Downloader/DASH/segments.py,sha256=oiip_q3QOY_c17_t66D0m974hyzsQXivhHY5-uE9dlQ,12747
74
- StreamingCommunity/Lib/Downloader/HLS/downloader.py,sha256=5ZOflDthkkmgZIGyLzL1Ao6ltyoJkQ7wAFe744Dyppk,21294
75
- StreamingCommunity/Lib/Downloader/HLS/segments.py,sha256=YqlG628N7I0STPQhchw5LM7kerv8XjTzdzh8N-dw2QM,17914
74
+ StreamingCommunity/Lib/Downloader/HLS/downloader.py,sha256=RqiLBZnKujbYqkmEAgqKnxmjJF2ar0nA__UEWFIDn68,21839
75
+ StreamingCommunity/Lib/Downloader/HLS/segments.py,sha256=SH1GCl4SObqqQoLiDwLDf3NTrjJoIgFby9Bqlt4s2Vo,17916
76
76
  StreamingCommunity/Lib/Downloader/MP4/downloader.py,sha256=_z61uQVnlfh-ktWYTisfbg_a4C3tpK7MO8HUdgLhTpI,8060
77
77
  StreamingCommunity/Lib/Downloader/TOR/downloader.py,sha256=tYOCuKkKDcTIJ-2bGIeplovRkLTdp89i8lUvJs_N9jc,19133
78
78
  StreamingCommunity/Lib/FFmpeg/__init__.py,sha256=NZmOXpnc5jvdvjNnHPxvj5bzp0GUuNMXd00Fcy4rQPI,258
79
79
  StreamingCommunity/Lib/FFmpeg/capture.py,sha256=UUBaFK8WLkvqxsElqyEj-JvDvd9zUFZ2bRwRoUcGjVk,5039
80
- StreamingCommunity/Lib/FFmpeg/command.py,sha256=E8EuihojWwMdxWYgZOEcjd-EUkh9il24bQBtphEV2n0,10679
81
- StreamingCommunity/Lib/FFmpeg/util.py,sha256=_ep_Jxm1_TfNphemtgS2whd6BFqMtK_IQmW_jRmFys8,9297
80
+ StreamingCommunity/Lib/FFmpeg/command.py,sha256=WNPBgEy9I2JRGbO_c4wZzmu0Knx2tx08V2WCrUgAwpA,12654
81
+ StreamingCommunity/Lib/FFmpeg/util.py,sha256=enx5Z29A4aHkq09iaP80NVMttQn9PZ8ruGe6GvURjGk,9515
82
82
  StreamingCommunity/Lib/M3U8/__init__.py,sha256=Zxij4WFCxjwyfswUfBv0oys_o0vQpAL5PoK5TGG_StY,288
83
83
  StreamingCommunity/Lib/M3U8/decryptor.py,sha256=1IutV-rZm3XLWGw1sEkApa3VkdwBc7BcC8AfyJ_zrrg,2965
84
84
  StreamingCommunity/Lib/M3U8/estimator.py,sha256=S4pa4hBgtJsh11mmQcpQK_1_xhkb9fHrIZdfWBxEbAg,5592
@@ -91,7 +91,7 @@ StreamingCommunity/TelegramHelp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm
91
91
  StreamingCommunity/TelegramHelp/config.json,sha256=v7FjA4smyLWZxChATewmvxDjJcclOCRZ_BIFPJd8Jvc,1374
92
92
  StreamingCommunity/TelegramHelp/telegram_bot.py,sha256=KiurpTrgiUNyMcLfceseaxV4xGegCUSJ8YttSeGXhJM,26429
93
93
  StreamingCommunity/Upload/update.py,sha256=9DStkCA_GGHjf47eDjUe-YeQ2mXhjmY-6E5C-HAwPlo,3829
94
- StreamingCommunity/Upload/version.py,sha256=4e7vj7d6prEkm_3AF-tkZtIZ_DTn6sEocD_tl9G52mg,171
94
+ StreamingCommunity/Upload/version.py,sha256=8GQwLbyQwIIaG_jRKVooDEaiM4x6UJJF-eo9SHw0G3A,171
95
95
  StreamingCommunity/Util/bento4_installer.py,sha256=P5ipziMCvezxan8GUh9vm8B1LXGyHusFVDf842LSwis,6966
96
96
  StreamingCommunity/Util/color.py,sha256=NvD0Eni-25oOOkY-szCEoc0lGvzQxyL7xhM0RE4EvUM,458
97
97
  StreamingCommunity/Util/config_json.py,sha256=vB6o6J5V874_bp9Y87VCCxp2wig0P3vwz4--zVokH4o,28576
@@ -102,9 +102,9 @@ StreamingCommunity/Util/logger.py,sha256=9kGD6GmWj2pM8ADpJc85o7jm8DD0c5Aguqnq-9k
102
102
  StreamingCommunity/Util/message.py,sha256=tstYQ9NxlfWupYkqPrOqOLqrKEb1iG5NsvIMNTUXXvA,1332
103
103
  StreamingCommunity/Util/os.py,sha256=VgKPcQxFTU_aCDpIw-T-z61xl9sCCAWZZdc0UZBieu8,17135
104
104
  StreamingCommunity/Util/table.py,sha256=xXfgd09oIYSxpJwnnkPZdWJ0DcCihSqxfvYYAEo-YMA,9806
105
- streamingcommunity-3.3.0.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
106
- streamingcommunity-3.3.0.dist-info/METADATA,sha256=uD8xka-sTPeGZIh7ZQEtlVYFx3qf1w9whuHQIrY2TuQ,27468
107
- streamingcommunity-3.3.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
108
- streamingcommunity-3.3.0.dist-info/entry_points.txt,sha256=Qph9XYfDC8n4LfDLOSl6gJGlkb9eFb5f-JOr_Wb_5rk,67
109
- streamingcommunity-3.3.0.dist-info/top_level.txt,sha256=YsOcxKP-WOhWpIWgBlh0coll9XUx7aqmRPT7kmt3fH0,19
110
- streamingcommunity-3.3.0.dist-info/RECORD,,
105
+ streamingcommunity-3.3.1.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
106
+ streamingcommunity-3.3.1.dist-info/METADATA,sha256=JXI1Q9AzFDz0tbOn7gZd43PXslZDWM8sjj_fBoobMSU,27157
107
+ streamingcommunity-3.3.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
108
+ streamingcommunity-3.3.1.dist-info/entry_points.txt,sha256=Qph9XYfDC8n4LfDLOSl6gJGlkb9eFb5f-JOr_Wb_5rk,67
109
+ streamingcommunity-3.3.1.dist-info/top_level.txt,sha256=YsOcxKP-WOhWpIWgBlh0coll9XUx7aqmRPT7kmt3fH0,19
110
+ streamingcommunity-3.3.1.dist-info/RECORD,,