StreamingCommunity 2.7.0__py3-none-any.whl → 2.9.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of StreamingCommunity might be problematic. Click here for more details.

Files changed (71) hide show
  1. StreamingCommunity/Api/Player/ddl.py +2 -2
  2. StreamingCommunity/Api/Player/maxstream.py +7 -13
  3. StreamingCommunity/Api/Player/supervideo.py +7 -33
  4. StreamingCommunity/Api/Player/vixcloud.py +8 -80
  5. StreamingCommunity/Api/Site/1337xx/__init__.py +8 -1
  6. StreamingCommunity/Api/Site/1337xx/site.py +10 -16
  7. StreamingCommunity/Api/Site/1337xx/title.py +4 -1
  8. StreamingCommunity/Api/Site/animeunity/__init__.py +9 -2
  9. StreamingCommunity/Api/Site/animeunity/film_serie.py +7 -1
  10. StreamingCommunity/Api/Site/animeunity/site.py +8 -10
  11. StreamingCommunity/Api/Site/animeunity/util/ScrapeSerie.py +1 -1
  12. StreamingCommunity/Api/Site/cb01new/__init__.py +8 -1
  13. StreamingCommunity/Api/Site/cb01new/film.py +10 -6
  14. StreamingCommunity/Api/Site/cb01new/site.py +16 -15
  15. StreamingCommunity/Api/Site/ddlstreamitaly/__init__.py +9 -2
  16. StreamingCommunity/Api/Site/ddlstreamitaly/series.py +7 -1
  17. StreamingCommunity/Api/Site/ddlstreamitaly/site.py +10 -15
  18. StreamingCommunity/Api/Site/ddlstreamitaly/util/ScrapeSerie.py +1 -1
  19. StreamingCommunity/Api/Site/guardaserie/__init__.py +9 -2
  20. StreamingCommunity/Api/Site/guardaserie/series.py +13 -8
  21. StreamingCommunity/Api/Site/guardaserie/site.py +12 -17
  22. StreamingCommunity/Api/Site/guardaserie/util/ScrapeSerie.py +1 -1
  23. StreamingCommunity/Api/Site/mostraguarda/__init__.py +6 -2
  24. StreamingCommunity/Api/Site/mostraguarda/film.py +10 -8
  25. StreamingCommunity/Api/Site/streamingcommunity/__init__.py +9 -2
  26. StreamingCommunity/Api/Site/streamingcommunity/film.py +11 -6
  27. StreamingCommunity/Api/Site/streamingcommunity/series.py +17 -10
  28. StreamingCommunity/Api/Site/streamingcommunity/site.py +10 -15
  29. StreamingCommunity/Api/Site/streamingcommunity/util/ScrapeSerie.py +2 -2
  30. StreamingCommunity/Api/Template/Util/__init__.py +0 -1
  31. StreamingCommunity/Api/Template/Util/get_domain.py +24 -66
  32. StreamingCommunity/Api/Template/Util/manage_ep.py +10 -5
  33. StreamingCommunity/Api/Template/config_loader.py +8 -8
  34. StreamingCommunity/Api/Template/site.py +3 -6
  35. StreamingCommunity/Lib/Downloader/HLS/downloader.py +15 -14
  36. StreamingCommunity/Lib/Downloader/HLS/segments.py +11 -31
  37. StreamingCommunity/Lib/Downloader/MP4/downloader.py +12 -9
  38. StreamingCommunity/Lib/Downloader/TOR/downloader.py +109 -101
  39. StreamingCommunity/Lib/FFmpeg/__init__.py +1 -1
  40. StreamingCommunity/Lib/FFmpeg/capture.py +10 -12
  41. StreamingCommunity/Lib/FFmpeg/command.py +15 -14
  42. StreamingCommunity/Lib/FFmpeg/util.py +9 -38
  43. StreamingCommunity/Lib/M3U8/decryptor.py +72 -146
  44. StreamingCommunity/Lib/M3U8/estimator.py +8 -16
  45. StreamingCommunity/Lib/M3U8/parser.py +25 -27
  46. StreamingCommunity/Lib/M3U8/url_fixer.py +1 -4
  47. StreamingCommunity/Lib/TMBD/__init__.py +2 -0
  48. StreamingCommunity/Lib/TMBD/obj_tmbd.py +3 -17
  49. StreamingCommunity/Lib/TMBD/tmdb.py +4 -9
  50. StreamingCommunity/TelegramHelp/telegram_bot.py +50 -50
  51. StreamingCommunity/Upload/update.py +3 -2
  52. StreamingCommunity/Upload/version.py +1 -1
  53. StreamingCommunity/Util/color.py +1 -1
  54. StreamingCommunity/Util/{_jsonConfig.py → config_json.py} +148 -54
  55. StreamingCommunity/Util/headers.py +2 -38
  56. StreamingCommunity/Util/logger.py +72 -42
  57. StreamingCommunity/Util/message.py +8 -3
  58. StreamingCommunity/Util/os.py +41 -93
  59. StreamingCommunity/Util/table.py +8 -17
  60. StreamingCommunity/run.py +26 -34
  61. {StreamingCommunity-2.7.0.dist-info → StreamingCommunity-2.9.0.dist-info}/METADATA +165 -92
  62. StreamingCommunity-2.9.0.dist-info/RECORD +75 -0
  63. StreamingCommunity/Api/Template/Util/recall_search.py +0 -37
  64. StreamingCommunity/Lib/Downloader/HLS/proxyes.py +0 -110
  65. StreamingCommunity/Util/call_stack.py +0 -42
  66. StreamingCommunity/Util/console.py +0 -12
  67. StreamingCommunity-2.7.0.dist-info/RECORD +0 -79
  68. {StreamingCommunity-2.7.0.dist-info → StreamingCommunity-2.9.0.dist-info}/LICENSE +0 -0
  69. {StreamingCommunity-2.7.0.dist-info → StreamingCommunity-2.9.0.dist-info}/WHEEL +0 -0
  70. {StreamingCommunity-2.7.0.dist-info → StreamingCommunity-2.9.0.dist-info}/entry_points.txt +0 -0
  71. {StreamingCommunity-2.7.0.dist-info → StreamingCommunity-2.9.0.dist-info}/top_level.txt +0 -0
@@ -3,163 +3,89 @@
3
3
  import sys
4
4
  import time
5
5
  import logging
6
- import subprocess
7
6
  import importlib.util
8
7
 
9
8
 
10
- # Internal utilities
11
- from StreamingCommunity.Util.console import console
9
+ # External library
10
+ from rich.console import Console
12
11
 
13
12
 
14
- # Check if Crypto module is installed
13
+ # Check if Cryptodome module is installed
14
+ console = Console()
15
15
  crypto_spec = importlib.util.find_spec("Cryptodome")
16
16
  crypto_installed = crypto_spec is not None
17
17
 
18
+ if not crypto_installed:
19
+ console.log("[red]pycryptodomex non è installato. Per favore installalo. Leggi readme.md [Requirement].")
20
+ sys.exit(0)
18
21
 
19
- if crypto_installed:
20
- logging.info("[cyan]Decrypy use: Cryptodomex")
21
- from Cryptodome.Cipher import AES
22
- from Cryptodome.Util.Padding import unpad
22
+ logging.info("[cyan]Decrypy use: Cryptodomex")
23
+ from Cryptodome.Cipher import AES
24
+ from Cryptodome.Util.Padding import unpad
23
25
 
24
- class M3U8_Decryption:
26
+
27
+
28
+ class M3U8_Decryption:
29
+ """
30
+ Class for decrypting M3U8 playlist content using AES with pycryptodomex.
31
+ """
32
+ def __init__(self, key: bytes, iv: bytes, method: str) -> None:
25
33
  """
26
- Class for decrypting M3U8 playlist content using AES encryption when the Crypto module is available.
34
+ Initialize the M3U8_Decryption object.
35
+
36
+ Parameters:
37
+ key (bytes): The encryption key.
38
+ iv (bytes): The initialization vector (IV).
39
+ method (str): The encryption method.
27
40
  """
28
- def __init__(self, key: bytes, iv: bytes, method: str) -> None:
29
- """
30
- Initialize the M3U8_Decryption object.
31
-
32
- Parameters:
33
- - key (bytes): The encryption key.
34
- - iv (bytes): The initialization vector (IV).
35
- - method (str): The encryption method.
36
- """
37
- self.key = key
38
- self.iv = iv
39
- if "0x" in str(iv):
40
- self.iv = bytes.fromhex(iv.replace("0x", ""))
41
- self.method = method
42
-
43
- # Precreate cipher based on encryption method
44
- if self.method == "AES":
45
- self.cipher = AES.new(self.key, AES.MODE_ECB)
46
- elif self.method == "AES-128":
47
- self.cipher = AES.new(self.key[:16], AES.MODE_CBC, iv=self.iv)
48
- elif self.method == "AES-128-CTR":
49
- self.cipher = AES.new(self.key[:16], AES.MODE_CTR, nonce=self.iv)
50
- else:
51
- raise ValueError("Invalid or unsupported method")
52
-
53
- def decrypt(self, ciphertext: bytes) -> bytes:
54
- """
55
- Decrypt the ciphertext using the specified encryption method.
56
-
57
- Parameters:
58
- - ciphertext (bytes): The encrypted content to decrypt.
59
-
60
- Returns:
61
- bytes: The decrypted content.
62
- """
63
- start = time.perf_counter_ns()
64
- #logging.info(f"Ciphertext: {ciphertext}")
65
-
66
- # Decrypt based on encryption method
67
- if self.method in {"AES", "AES-128"}:
68
- decrypted_data = self.cipher.decrypt(ciphertext)
69
- decrypted_content = unpad(decrypted_data, AES.block_size)
70
-
71
- elif self.method == "AES-128-CTR":
72
- decrypted_content = self.cipher.decrypt(ciphertext)
73
- else:
74
- raise ValueError("Invalid or unsupported method")
75
-
76
- end = time.perf_counter_ns()
77
-
78
- # Calculate elapsed time with high precision
79
- elapsed_nanoseconds = end - start
80
- elapsed_milliseconds = elapsed_nanoseconds / 1_000_000
81
- elapsed_seconds = elapsed_nanoseconds / 1_000_000_000
82
-
83
- # Print performance metrics
84
- logging.info(f"[Crypto Decryption Performance]")
85
- logging.info(f"Method: {self.method}")
86
- logging.info(f"Decryption Time: {elapsed_milliseconds:.4f} ms ({elapsed_seconds:.6f} s)")
87
- logging.info(f"Decrypted Content Length: {len(decrypted_content)} bytes")
88
-
89
- return decrypted_content
90
-
91
-
92
- else:
93
-
94
- # Check if openssl command is available
95
- try:
96
- openssl_available = subprocess.run(["openssl", "version"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL).returncode == 0
97
- logging.info("[cyan]Decrypy use: OPENSSL")
98
- except:
99
- openssl_available = False
100
-
101
- if not openssl_available:
102
- console.log("[red]Neither python library: pycryptodomex nor openssl software is installed. Please install either one of them. Read readme.md [Requirement].")
103
- sys.exit(0)
104
-
105
- class M3U8_Decryption:
41
+ self.key = key
42
+ self.iv = iv
43
+ if "0x" in str(iv):
44
+ self.iv = bytes.fromhex(iv.replace("0x", ""))
45
+ self.method = method
46
+
47
+ # Pre-create the cipher based on the encryption method
48
+ if self.method == "AES":
49
+ self.cipher = AES.new(self.key, AES.MODE_ECB)
50
+ elif self.method == "AES-128":
51
+ self.cipher = AES.new(self.key[:16], AES.MODE_CBC, iv=self.iv)
52
+ elif self.method == "AES-128-CTR":
53
+ self.cipher = AES.new(self.key[:16], AES.MODE_CTR, nonce=self.iv)
54
+ else:
55
+ raise ValueError("Invalid or unsupported method")
56
+
57
+ def decrypt(self, ciphertext: bytes) -> bytes:
58
+ """
59
+ Decrypt the ciphertext using the specified encryption method.
60
+
61
+ Parameters:
62
+ ciphertext (bytes): The encrypted content to decrypt.
63
+
64
+ Returns:
65
+ bytes: The decrypted content.
66
+ """
67
+ #start = time.perf_counter_ns()
68
+
69
+ if self.method in {"AES", "AES-128"}:
70
+ decrypted_data = self.cipher.decrypt(ciphertext)
71
+ decrypted_content = unpad(decrypted_data, AES.block_size)
72
+ elif self.method == "AES-128-CTR":
73
+ decrypted_content = self.cipher.decrypt(ciphertext)
74
+ else:
75
+ raise ValueError("Invalid or unsupported method")
76
+
106
77
  """
107
- Class for decrypting M3U8 playlist content using OpenSSL when the Crypto module is not available.
78
+ end = time.perf_counter_ns()
79
+
80
+ # Calculate the elapsed time with high precision
81
+ elapsed_nanoseconds = end - start
82
+ elapsed_milliseconds = elapsed_nanoseconds / 1_000_000
83
+ elapsed_seconds = elapsed_nanoseconds / 1_000_000_000
84
+
85
+ # Log performance metrics
86
+ logging.info("[Crypto Decryption Performance]")
87
+ logging.info(f"Method: {self.method}")
88
+ logging.info(f"Decryption Time: {elapsed_milliseconds:.4f} ms ({elapsed_seconds:.6f} s)")
89
+ logging.info(f"Decrypted Content Length: {len(decrypted_content)} bytes")
108
90
  """
109
- def __init__(self, key: bytes, iv: bytes, method: str) -> None:
110
- """
111
- Initialize the M3U8_Decryption object.
112
-
113
- Parameters:
114
- - key (bytes): The encryption key.
115
- - iv (bytes): The initialization vector (IV).
116
- - method (str): The encryption method.
117
- """
118
- self.key = key
119
- self.iv = iv
120
- if "0x" in str(iv):
121
- self.iv = bytes.fromhex(iv.replace("0x", ""))
122
- self.method = method
123
- logging.info(f"Decrypt add: ('key': {self.key}, 'iv': {self.iv}, 'method': {self.method})")
124
-
125
- def decrypt(self, ciphertext: bytes) -> bytes:
126
- """
127
- Decrypt the ciphertext using the specified encryption method.
128
-
129
- Parameters:
130
- - ciphertext (bytes): The encrypted content to decrypt.
131
-
132
- Returns:
133
- bytes: The decrypted content.
134
- """
135
- start = time.perf_counter_ns()
136
-
137
- # Construct OpenSSL command based on encryption method
138
- if self.method == "AES":
139
- openssl_cmd = f'openssl enc -d -aes-256-ecb -K {self.key.hex()} -nosalt'
140
- elif self.method == "AES-128":
141
- openssl_cmd = f'openssl enc -d -aes-128-cbc -K {self.key[:16].hex()} -iv {self.iv.hex()}'
142
- elif self.method == "AES-128-CTR":
143
- openssl_cmd = f'openssl enc -d -aes-128-ctr -K {self.key[:16].hex()} -iv {self.iv.hex()}'
144
- else:
145
- raise ValueError("Invalid or unsupported method")
146
-
147
- try:
148
- decrypted_content = subprocess.check_output(openssl_cmd.split(), input=ciphertext, stderr=subprocess.STDOUT)
149
- except subprocess.CalledProcessError as e:
150
- raise ValueError(f"Decryption failed: {e.output.decode()}")
151
-
152
- end = time.perf_counter_ns()
153
-
154
- # Calculate elapsed time with high precision
155
- elapsed_nanoseconds = end - start
156
- elapsed_milliseconds = elapsed_nanoseconds / 1_000_000
157
- elapsed_seconds = elapsed_nanoseconds / 1_000_000_000
158
-
159
- # Print performance metrics
160
- logging.info(f"[OpenSSL Decryption Performance]")
161
- logging.info(f"Method: {self.method}")
162
- logging.info(f"Decryption Time: {elapsed_milliseconds:.4f} ms ({elapsed_seconds:.6f} s)")
163
- logging.info(f"Decrypted Content Length: {len(decrypted_content)} bytes")
164
-
165
- return decrypted_content
91
+ return decrypted_content
@@ -14,13 +14,10 @@ from tqdm import tqdm
14
14
 
15
15
  # Internal utilities
16
16
  from StreamingCommunity.Util.color import Colors
17
+ from StreamingCommunity.Util.config_json import get_use_large_bar
17
18
  from StreamingCommunity.Util.os import internet_manager
18
19
 
19
20
 
20
- # Variable
21
- USE_LARGE_BAR = not ("android" in sys.platform or "ios" in sys.platform)
22
-
23
-
24
21
  class M3U8_Ts_Estimator:
25
22
  def __init__(self, total_segments: int, segments_instance=None):
26
23
  """
@@ -36,7 +33,7 @@ class M3U8_Ts_Estimator:
36
33
  self.lock = threading.Lock()
37
34
  self.speed = {"upload": "N/A", "download": "N/A"}
38
35
 
39
- if USE_LARGE_BAR:
36
+ if get_use_large_bar():
40
37
  logging.debug("USE_LARGE_BAR is True, starting speed capture thread")
41
38
  self.speed_thread = threading.Thread(target=self.capture_speed)
42
39
  self.speed_thread.daemon = True
@@ -106,15 +103,11 @@ class M3U8_Ts_Estimator:
106
103
  try:
107
104
  self.add_ts_file(total_downloaded * self.total_segments, total_downloaded, duration)
108
105
 
109
- #downloaded_file_size_str = internet_manager.format_file_size(self.now_downloaded_size)
110
106
  file_total_size = self.calculate_total_size()
111
-
112
- #number_file_downloaded = downloaded_file_size_str.split(' ')[0]
113
107
  number_file_total_size = file_total_size.split(' ')[0]
114
- #units_file_downloaded = downloaded_file_size_str.split(' ')[1]
115
108
  units_file_total_size = file_total_size.split(' ')[1]
116
109
 
117
- if USE_LARGE_BAR:
110
+ if get_use_large_bar():
118
111
  speed_data = self.speed['download'].split(" ")
119
112
 
120
113
  if len(speed_data) >= 2:
@@ -126,17 +119,16 @@ class M3U8_Ts_Estimator:
126
119
 
127
120
  retry_count = self.segments_instance.active_retries if self.segments_instance else 0
128
121
  progress_str = (
129
- #f"{Colors.WHITE}[ {Colors.GREEN}{number_file_downloaded} {Colors.WHITE}< "
130
- f"{Colors.GREEN}{number_file_total_size} {Colors.RED}{units_file_total_size}"
122
+ f"{Colors.GREEN}{number_file_total_size} {Colors.WHITE}< {Colors.RED}{units_file_total_size}"
131
123
  f"{Colors.WHITE} {Colors.CYAN}{average_internet_speed} {Colors.RED}{average_internet_unit}"
132
- f"{Colors.WHITE} {Colors.GREEN}CRR {Colors.RED}{retry_count} "
124
+ f"{Colors.WHITE}, {Colors.GREEN}CRR {Colors.RED}{retry_count} "
133
125
  )
126
+
134
127
  else:
135
128
  retry_count = self.segments_instance.active_retries if self.segments_instance else 0
136
129
  progress_str = (
137
- #f"{Colors.WHITE}[ {Colors.GREEN}{number_file_downloaded} {Colors.WHITE}< "
138
- f"{Colors.GREEN}{number_file_total_size} {Colors.RED}{units_file_total_size}"
139
- f"{Colors.WHITE} {Colors.GREEN}CRR {Colors.RED}{retry_count} "
130
+ f"{Colors.GREEN}{number_file_total_size} {Colors.WHITE}< {Colors.RED}{units_file_total_size}"
131
+ f"{Colors.WHITE}, {Colors.GREEN}CRR {Colors.RED}{retry_count} "
140
132
  )
141
133
 
142
134
  progress_counter.set_postfix_str(progress_str)
@@ -9,10 +9,6 @@ from m3u8 import loads
9
9
  from StreamingCommunity.Util.os import internet_manager
10
10
 
11
11
 
12
- # External libraries
13
- import httpx
14
-
15
-
16
12
  # Costant
17
13
  CODEC_MAPPINGS = {
18
14
  "video": {
@@ -79,7 +75,6 @@ class M3U8_Codec:
79
75
  Extracted codecs are set as attributes: audio_codec and video_codec.
80
76
  """
81
77
  try:
82
- # Split the codecs string by comma
83
78
  codecs_list = self.codecs.split(',')
84
79
  except Exception as e:
85
80
  logging.error(f"Can't split codec list: {self.codecs} with error {e}")
@@ -407,10 +402,8 @@ class M3U8_Parser:
407
402
  Parameters:
408
403
  - m3u8_content (str): The content of the M3U8 file.
409
404
  """
410
-
411
- # Get obj of the m3u8 text content download, dictionary with video, audio, segments, subtitles
412
405
  m3u8_obj = loads(raw_content, uri)
413
-
406
+
414
407
  self.__parse_video_info__(m3u8_obj)
415
408
  self.__parse_subtitles_and_audio__(m3u8_obj)
416
409
  self.__parse_segments__(m3u8_obj)
@@ -469,7 +462,6 @@ class M3U8_Parser:
469
462
  Parameters:
470
463
  - m3u8_obj: The M3U8 object containing video playlists.
471
464
  """
472
-
473
465
  try:
474
466
  for playlist in m3u8_obj.playlists:
475
467
 
@@ -511,25 +503,35 @@ class M3U8_Parser:
511
503
  except Exception as e:
512
504
  logging.error(f"Error parsing video info: {e}")
513
505
 
514
- def __parse_encryption_keys__(self, m3u8_obj) -> None:
506
+ def __parse_encryption_keys__(self, obj) -> None:
515
507
  """
516
- Extracts encryption keys from the M3U8 object.
508
+ Extracts encryption keys either from the M3U8 object or from individual segments.
517
509
 
518
510
  Parameters:
519
- - m3u8_obj: The M3U8 object containing encryption keys.
511
+ - obj: Either the main M3U8 object or an individual segment.
520
512
  """
521
513
  try:
522
- if m3u8_obj.key is not None:
514
+ if hasattr(obj, 'key') and obj.key is not None:
515
+ key_info = {
516
+ 'method': obj.key.method,
517
+ 'iv': obj.key.iv,
518
+ 'uri': obj.key.uri
519
+ }
520
+
523
521
  if self.keys is None:
524
- self.keys = {
525
- 'method': m3u8_obj.key.method,
526
- 'iv': m3u8_obj.key.iv,
527
- 'uri': m3u8_obj.key.uri
528
- }
522
+ self.keys = key_info
523
+
524
+ """
525
+ elif obj.key.uri not in self.keys:
526
+ if isinstance(self.keys, dict):
527
+ self.keys[obj.key.uri] = key_info
528
+ else:
529
+ old_key = self.keys
530
+ self.keys = {'default': old_key, obj.key.uri: key_info}
531
+ """
529
532
 
530
533
  except Exception as e:
531
534
  logging.error(f"Error parsing encryption keys: {e}")
532
- sys.exit(0)
533
535
  pass
534
536
 
535
537
  def __parse_subtitles_and_audio__(self, m3u8_obj) -> None:
@@ -569,7 +571,6 @@ class M3U8_Parser:
569
571
  Parameters:
570
572
  - m3u8_obj: The M3U8 object containing segment data.
571
573
  """
572
-
573
574
  try:
574
575
  for segment in m3u8_obj.segments:
575
576
 
@@ -583,6 +584,10 @@ class M3U8_Parser:
583
584
  self.segments.append(segment.uri)
584
585
  else:
585
586
  self.subtitle.append(segment.uri)
587
+
588
+ # Second check if there is key in main m3u8 obj
589
+ if self.keys is None:
590
+ self.__parse_encryption_keys__(m3u8_obj)
586
591
 
587
592
  except Exception as e:
588
593
  logging.error(f"Error parsing segments: {e}")
@@ -606,13 +611,6 @@ class M3U8_Parser:
606
611
  Returns:
607
612
  - formatted_duration (str): Formatted duration string with hours, minutes, and seconds if return_string is True.
608
613
  - duration_dict (dict): Dictionary with keys 'h', 'm', 's' representing hours, minutes, and seconds respectively if return_string is False.
609
-
610
- Example usage:
611
- >>> obj = YourClass(duration=3661)
612
- >>> obj.get_duration()
613
- '[yellow]1[red]h [yellow]1[red]m [yellow]1[red]s'
614
- >>> obj.get_duration(return_string=False)
615
- {'h': 1, 'm': 1, 's': 1}
616
614
  """
617
615
 
618
616
  # Calculate hours, minutes, and remaining seconds
@@ -33,8 +33,6 @@ class M3U8_UrlFix:
33
33
  Returns:
34
34
  str: The full URL for the specified resource.
35
35
  """
36
-
37
- # Check if m3u8 url playlist is present
38
36
  if self.url_playlist == None:
39
37
  logging.error("[M3U8_UrlFix] Cant generate full url, playlist not present")
40
38
  raise
@@ -54,5 +52,4 @@ class M3U8_UrlFix:
54
52
  """
55
53
  Reset the M3U8 playlist URL to its default state (None).
56
54
  """
57
- self.url_playlist = None
58
-
55
+ self.url_playlist = None
@@ -1,2 +1,4 @@
1
+ # 17.09.24
2
+
1
3
  from .tmdb import tmdb
2
4
  from .obj_tmbd import Json_film
@@ -5,35 +5,21 @@ from typing import Dict
5
5
 
6
6
  class Json_film:
7
7
  def __init__(self, data: Dict):
8
- self.adult = data.get('adult', False)
9
- self.backdrop_path = data.get('backdrop_path')
10
- self.budget = data.get('budget', 0)
11
- self.homepage = data.get('homepage')
12
8
  self.id = data.get('id', 0)
13
9
  self.imdb_id = data.get('imdb_id')
14
10
  self.origin_country = data.get('origin_country', [])
15
11
  self.original_language = data.get('original_language')
16
12
  self.original_title = data.get('original_title')
17
- self.overview = data.get('overview')
18
13
  self.popularity = data.get('popularity', 0.0)
19
14
  self.poster_path = data.get('poster_path')
20
15
  self.release_date = data.get('release_date')
21
- self.revenue = data.get('revenue', 0)
22
- self.runtime = data.get('runtime', 0)
23
16
  self.status = data.get('status')
24
- self.tagline = data.get('tagline')
25
17
  self.title = data.get('title')
26
- self.video = data.get('video', False)
27
18
  self.vote_average = data.get('vote_average', 0.0)
28
19
  self.vote_count = data.get('vote_count', 0)
29
20
 
30
21
  def __repr__(self):
31
- return (f"Film(adult={self.adult}, backdrop_path='{self.backdrop_path}', "
32
- f"budget={self.budget}, "
33
- f"homepage='{self.homepage}', id={self.id}, "
34
- f"imdb_id='{self.imdb_id}', origin_country={self.origin_country}, "
22
+ return (f"Json_film(id={self.id}, imdb_id='{self.imdb_id}', origin_country={self.origin_country}, "
35
23
  f"original_language='{self.original_language}', original_title='{self.original_title}', "
36
- f"overview='{self.overview}', popularity={self.popularity}, poster_path='{self.poster_path}', "
37
- f"release_date='{self.release_date}', revenue={self.revenue}, runtime={self.runtime}, "
38
- f"status='{self.status}', tagline='{self.tagline}', "
39
- f"title='{self.title}', video={self.video}, vote_average={self.vote_average}, vote_count={self.vote_count})")
24
+ f"popularity={self.popularity}, poster_path='{self.poster_path}', release_date='{self.release_date}', "
25
+ f"status='{self.status}', title='{self.title}', vote_average={self.vote_average}, vote_count={self.vote_count})")
@@ -6,22 +6,22 @@ from typing import Dict
6
6
 
7
7
  # External libraries
8
8
  import httpx
9
+ from rich.console import Console
9
10
 
10
11
 
11
12
  # Internal utilities
12
13
  from .obj_tmbd import Json_film
13
- from StreamingCommunity.Util.console import console
14
- from StreamingCommunity.Util._jsonConfig import config_manager
14
+ from StreamingCommunity.Util.config_json import config_manager
15
15
  from StreamingCommunity.Util.table import TVShowManager
16
16
 
17
17
 
18
18
  # Variable
19
+ console = Console()
19
20
  table_show_manager = TVShowManager()
20
21
  api_key = "a800ed6c93274fb857ea61bd9e7256c5"
21
22
  MAX_TIMEOUT = config_manager.get_int("REQUESTS", "timeout")
22
23
 
23
24
 
24
-
25
25
  def get_select_title(table_show_manager, generic_obj):
26
26
  """
27
27
  Display a selection of titles and prompt the user to choose one.
@@ -29,11 +29,6 @@ def get_select_title(table_show_manager, generic_obj):
29
29
  Returns:
30
30
  dict: The selected media item.
31
31
  """
32
-
33
- # Set up table for displaying titles
34
- table_show_manager.set_slice_end(10)
35
-
36
- # Check if the generic_obj list is empty
37
32
  if not generic_obj:
38
33
  console.print("\n[red]No media items available.")
39
34
  return None
@@ -158,7 +153,7 @@ class TheMovieDB:
158
153
 
159
154
  # Join with colored arrows and print with proper category label
160
155
  console.print(
161
- f"[bold purple]{category}:[/] {' [red][/] '.join(colored_items)}"
156
+ f"[bold purple]{category}:[/] {' [red]->[/] '.join(colored_items)}"
162
157
  )
163
158
 
164
159
  def display_trending_tv_shows(self):